Najlepszy sposób na zrobienie wielu konstruktorów w PHP

Nie można umieścić dwóch funkcji _ _ construct z unikalnymi podpisami argumentów w klasie PHP. Chciałbym to zrobić:

class Student 
{
   protected $id;
   protected $name;
   // etc.

   public function __construct($id){
       $this->id = $id;
      // other members are still uninitialized
   }

   public function __construct($row_from_database){
       $this->id = $row_from_database->id;
       $this->name = $row_from_database->name;
       // etc.
   }
}

Jaki jest najlepszy sposób na zrobienie tego w PHP?

Author: Jannie Theunissen, 2009-11-09

22 answers

Prawdopodobnie zrobiłbym coś takiego:

<?php

class Student
{
    public function __construct() {
        // allocate your stuff
    }

    public static function withID( $id ) {
        $instance = new self();
        $instance->loadByID( $id );
        return $instance;
    }

    public static function withRow( array $row ) {
        $instance = new self();
        $instance->fill( $row );
        return $instance;
    }

    protected function loadByID( $id ) {
        // do query
        $row = my_awesome_db_access_stuff( $id );
        $this->fill( $row );
    }

    protected function fill( array $row ) {
        // fill all properties from array
    }
}

?>

Więc jeśli chcę ucznia, w którym znam ID:

$student = Student::withID( $id );

Lub jeśli mam tablicę z wiersza db:

$student = Student::withRow( $row );

Technicznie nie budujesz wielu konstruktorów, tylko statyczne metody pomocnicze, ale w ten sposób unikasz dużej ilości kodu spaghetti w konstruktorze.

 499
Author: Kris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-09 14:33:09

Rozwiązanie Kris jest naprawdę fajne, ale mi się bardziej podoba mieszanka factory i fluent style:

<?php

class Student
{

    protected $firstName;
    protected $lastName;
    // etc.

    /**
     * Constructor
     */
    public function __construct() {
        // allocate your stuff
    }

    /**
     * Static constructor / factory
     */
    public static function create() {
        $instance = new self();
        return $instance;
    }

    /**
     * FirstName setter - fluent style
     */
    public function setFirstName( $firstName) {
        $this->firstName = $firstName;
        return $this;
    }

    /**
     * LastName setter - fluent style
     */
    public function setLastName( $lastName) {
        $this->lastName = $lastName;
        return $this;
    }

}

// create instance
$student= Student::create()->setFirstName("John")->setLastName("Doe");

// see result
var_dump($student);
?>
 88
Author: timaschew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-23 09:40:45

PHP jest językiem dynamicznym, więc nie można przeciążać metod. Musisz sprawdzić typy swoich argumentów w ten sposób:

class Student 
{
   protected $id;
   protected $name;
   // etc.

   public function __construct($idOrRow){
    if(is_int($idOrRow))
    {
        $this->id = $idOrRow;
        // other members are still uninitialized
    }
    else if(is_array($idOrRow))
    {
       $this->id = $idOrRow->id;
       $this->name = $idOrRow->name;
       // etc.  
    }
}
 44
Author: Daff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-19 05:41:16
public function __construct() {
    $parameters = func_get_args();
    ...
}

$o = new MyClass('One', 'Two', 3);

Teraz $paramters będzie tablicą o wartościach 'One', 'Two', 3.

Edit,

Mogę dodać, że

func_num_args()

Poda liczbę parametrów funkcji.

 25
Author: Björn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-09 08:47:58

Jak już pokazano tutaj, istnieje wiele sposobów deklarowania multiple konstruktorów w PHP, ale żaden z nich nie jest correct sposobem na to (ponieważ PHP technicznie na to nie pozwala). Ale to nie powstrzymuje nas przed hakowaniem tej funkcjonalności... Oto kolejny przykład:

<?php

class myClass {
    public function __construct() {
        $get_arguments       = func_get_args();
        $number_of_arguments = func_num_args();

        if (method_exists($this, $method_name = '__construct'.$number_of_arguments)) {
            call_user_func_array(array($this, $method_name), $get_arguments);
        }
    }

    public function __construct1($argument1) {
        echo 'constructor with 1 parameter ' . $argument1 . "\n";
    }

    public function __construct2($argument1, $argument2) {
        echo 'constructor with 2 parameter ' . $argument1 . ' ' . $argument2 . "\n";
    }

    public function __construct3($argument1, $argument2, $argument3) {
        echo 'constructor with 3 parameter ' . $argument1 . ' ' . $argument2 . ' ' . $argument3 . "\n";
    }
}

$object1 = new myClass('BUET');
$object2 = new myClass('BUET', 'is');
$object3 = new myClass('BUET', 'is', 'Best.');

Źródło: najprostszy sposób użycia i zrozumienia wielu konstruktorów:

Mam nadzieję, że to pomoże. :)
 23
Author: Nasif Md. Tanjim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-25 10:36:18

Mógłbyś zrobić coś takiego:

public function __construct($param)
{
    if(is_int($param)) {
         $this->id = $param;
    } elseif(is_object($param)) {
     // do something else
    }
 }
 15
Author: Andrei Serdeliuc ॐ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-09 08:47:43

Od wersji 5.4 PHP obsługuje traits . To jest nie dokładnie to, czego szukasz, ale uproszczone podejście oparte na cechach byłoby:

trait StudentTrait {
    protected $id;
    protected $name;

    final public function setId($id) {
        $this->id = $id;
        return $this;
    }

    final public function getId() { return $this->id; }

    final public function setName($name) {
        $this->name = $name; 
        return $this;
    }

    final public function getName() { return $this->name; }

}

class Student1 {
    use StudentTrait;

    final public function __construct($id) { $this->setId($id); }
}

class Student2 {
    use StudentTrait;

    final public function __construct($id, $name) { $this->setId($id)->setName($name); }
}

Kończymy z dwiema klasami, po jednej dla każdego konstruktora, co jest nieco nieproduktywne. Aby zachować trochę rozsądku, dorzucę fabrykę:

class StudentFactory {
    static public function getStudent($id, $name = null) {
        return 
            is_null($name)
                ? new Student1($id)
                : new Student2($id, $name)
    }
}

Więc wszystko sprowadza się do tego:

$student1 = StudentFactory::getStudent(1);
$student2 = StudentFactory::getStudent(1, "yannis");
To strasznie gadatliwe podejście, ale może być bardzo wygodne.
 15
Author: yannis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-01 08:45:29

Inną opcją jest użycie domyślnych argumentów w konstruktorze, takich jak Ta

class Student {

    private $id;
    private $name;
    //...

    public function __construct($id, $row=array()) {
        $this->id = $id;
        foreach($row as $key => $value) $this->$key = $value;
    }
}

Oznacza to, że będziesz musiał utworzyć instancję z takim wierszem: $student = new Student($row['id'], $row) ale twój konstruktor jest ładny i czysty.

Z drugiej strony, jeśli chcesz skorzystać z polimorfizmu, możesz utworzyć dwie klasy w ten sposób:

class Student {

    public function __construct($row) {
         foreach($row as $key => $value) $this->$key = $value;
    }
}

class EmptyStudent extends Student {

    public function __construct($id) {
        parent::__construct(array('id' => $id));
    }
}
 7
Author: rojoca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-09 10:03:24

Oto elegancki sposób na to. Utwórz cechę, która umożliwi wiele konstruktorów, biorąc pod uwagę liczbę parametrów. Wystarczy dodać liczbę parametrów do nazwy funkcji "_ _ construct". Więc jeden parametr będzie "_ _ construct1", dwa "_ _ construct2"... itd.

trait constructable
{
    public function __construct() 
    { 
        $a = func_get_args(); 
        $i = func_num_args(); 
        if (method_exists($this,$f='__construct'.$i)) { 
            call_user_func_array([$this,$f],$a); 
        } 
    } 
}

class a{
    use constructable;

    public $result;

    public function __construct1($a){
        $this->result = $a;
    }

    public function __construct2($a, $b){
        $this->result =  $a + $b;
    }
}

echo (new a(1))->result;    // 1
echo (new a(1,2))->result;  // 3
 7
Author: Jed Lynch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-21 21:58:16

Jak wspomniano w innych komentarzach, ponieważ php nie obsługuje przeciążania, zwykle unika się "sztuczek sprawdzania typu" w konstruktorze, a wzorzec fabryczny jest używany w intead

Ie.

$myObj = MyClass::factory('fromInteger', $params);
$myObj = MyClass::factory('fromRow', $params);
 4
Author: gpilotino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-09 10:09:27

Możesz zrobić coś takiego, co jest naprawdę łatwe i bardzo czyste:

public function __construct()    
{
   $arguments = func_get_args(); 

   switch(sizeof(func_get_args()))      
   {
    case 0: //No arguments
        break; 
    case 1: //One argument
        $this->do_something($arguments[0]); 
        break;              
    case 2:  //Two arguments
        $this->do_something_else($arguments[0], $arguments[1]); 
        break;            
   }
}
 4
Author: paishin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-02 22:21:42

Na to pytanie odpowiedziano już za pomocą bardzo inteligentnych sposobów spełnienia tego wymogu, ale zastanawiam się, dlaczego nie zrobić kroku wstecz i nie zadać podstawowego pytania, Dlaczego potrzebujemy klasy z dwoma konstruktorami? Jeśli moja klasa potrzebuje dwóch konstruktorów, to prawdopodobnie sposób, w jaki projektuję moje klasy, wymaga trochę więcej uwagi, aby wymyślić projekt, który jest czystszy i bardziej testowalny.

Próbujemy pomieszać sposób tworzenia instancji klasy z rzeczywistą logiką klasy.

If a Obiekt Student jest w stanie poprawnym, czy ma znaczenie, czy został zbudowany z wiersza DB lub danych z formularza internetowego lub żądania cli?

Teraz, aby odpowiedzieć na pytanie, które mogą się tutaj pojawić, że jeśli nie dodamy logiki tworzenia obiektu z wiersza db, to jak tworzymy obiekt z danych db, możemy po prostu dodać inną klasę, nazwij ją StudentMapper jeśli czujesz się komfortowo z wzorcem data mapper, w niektórych przypadkach możesz użyć StudentRepository i jeśli nic nie pasuje do twojego wzorca. potrzeby możesz zrobić StudentFactory do obsługi wszelkiego rodzaju zadań budowy obiektów.

Bottomline polega na tym, aby podczas pracy nad obiektami domenowymi utrzymać warstwę trwałości z głowy.

 3
Author: Waku-2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-16 06:21:15

Pozwól mi dodać moje ziarnko piasku tutaj

Osobiście lubię dodawać konstruktory jako funkcje statyczne, które zwracają instancję klasy (obiekt). Poniższy kod jest przykładem:

 class Person
 {
     private $name;
     private $email;

     public static function withName($name)
     {
         $person = new Person();
         $person->name = $name;

         return $person;
     }

     public static function withEmail($email)
     {
         $person = new Person();
         $person->email = $email;

         return $person;
     }
 }

Zauważ, że teraz możesz utworzyć instancję klasy Person w następujący sposób:

$person1 = Person::withName('Example');
$person2 = Person::withEmail('yo@mi_email.com');

Wziąłem ten kod z:

Http://alfonsojimenez.com/post/30377422731/multiple-constructors-in-php

 2
Author: Salvi Pascual,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-24 17:49:38

Wiem, że jestem bardzo spóźniony na imprezę tutaj, ale wymyśliłem dość elastyczny wzór, który powinien pozwolić na naprawdę ciekawe i wszechstronne implementacje.

Ustaw klasę tak, jak normalnie, z dowolnymi zmiennymi, które chcesz.

class MyClass{
    protected $myVar1;
    protected $myVar2;

    public function __construct($obj = null){
        if($obj){
            foreach (((object)$obj) as $key => $value) {
                if(isset($value) && in_array($key, array_keys(get_object_vars($this)))){
                    $this->$key = $value;
                }
            }
        }
    }
}

Kiedy sprawisz, że Twój obiekt po prostu przekaże tablicę asocjacyjną z kluczami tablicy tak samo jak nazwy Twoich VAR-ów, w ten sposób...

$sample_variable = new MyClass([
    'myVar2'=>123, 
    'i_dont_want_this_one'=> 'This won\'t make it into the class'
    ]);

print_r($sample_variable);

print_r($sample_variable); po tej instancji daje po:

MyClass Object ( [myVar1:protected] => [myVar2:protected] => 123 )

Ponieważ zainicjalizowaliśmy $group na null w naszym __construct(...), Ważne jest również przekazanie niczego do konstruktora, tak jak to...

$sample_variable = new MyClass();

print_r($sample_variable);

Teraz wyjście jest dokładnie takie, jak oczekiwano:

MyClass Object ( [myVar1:protected] => [myVar2:protected] => )

Powodem, dla którego to napisałem, było to, że mogłem bezpośrednio przekazać wyjście json_decode(...) do mojego konstruktora i nie martwić się o to zbytnio.

To zostało wykonane w PHP 7.1. Smacznego!

 2
Author: David Culbreth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-22 12:36:38

To jest moje podejście do tego (build for php 5.6).

Sprawdza typy parametrów konstruktora (tablica, nazwa klasy, Brak opisu) i porównuje podane argumenty. Konstruktory muszą być podane z najmniejszą dokładnością. Z przykładami:

// demo class
class X {
    public $X;

    public function __construct($x) {
        $this->X = $x;
    }

    public function __toString() {
        return 'X'.$this->X;
    }
}

// demo class
class Y {
    public $Y;

    public function __construct($y) {
        $this->Y = $y;
    }
    public function __toString() {
        return 'Y'.$this->Y;
    }
}

// here be magic
abstract class MultipleConstructors {
    function __construct() {
        $__get_arguments       = func_get_args();
        $__number_of_arguments = func_num_args();

        $__reflect = new ReflectionClass($this);
        foreach($__reflect->getMethods() as $__reflectmethod) {
            $__method_name = $__reflectmethod->getName();
            if (substr($__method_name, 0, strlen('__construct')) === '__construct') {
                $__parms = $__reflectmethod->getParameters();
                if (count($__parms) == $__number_of_arguments) {
                    $__argsFit = true;
                    foreach ($__parms as $__argPos => $__param) {
                        $__paramClass= $__param->getClass();
                        $__argVar = func_get_arg($__argPos);
                        $__argVarType = gettype($__argVar);
                        $__paramIsArray = $__param->isArray() == true;
                        $__argVarIsArray = $__argVarType == 'array';
                        // parameter is array and argument isn't, or the other way around.
                        if (($__paramIsArray && !$__argVarIsArray) ||
                            (!$__paramIsArray && $__argVarIsArray)) {
                            $__argsFit = false;
                            continue;
                        }
                        // class check
                        if ((!is_null($__paramClass) && $__argVarType != 'object') ||
                            (is_null($__paramClass) && $__argVarType == 'object')){
                            $__argsFit = false;
                            continue;
                        }
                        if (!is_null($__paramClass) && $__argVarType == 'object') {
                            // class type check
                            $__paramClassName = "N/A";
                            if ($__paramClass)
                                $__paramClassName = $__paramClass->getName();
                            if ($__paramClassName != get_class($__argVar)) {
                                $__argsFit = false;
                            }
                        }
                    }
                    if ($__argsFit) {
                        call_user_func_array(array($this, $__method_name), $__get_arguments);
                        return;
                    }
                }
            }
        }
        throw new Exception("No matching constructors");
    }
}

// how to use multiple constructors
class A extends MultipleConstructors {
    public $value;

    function __constructB(array $hey) {
        $this->value = 'Array#'.count($hey).'<br/>';
    }
    function __construct1(X $first) {
        $this->value = $first .'<br/>';
    }

    function __construct2(Y $second) {
        $this->value = $second .'<br/>';
    }
    function __constructA($hey) {
        $this->value = $hey.'<br/>';
    }

    function __toString() {
        return $this->value;
    }
}

$x = new X("foo");
$y = new Y("bar");

$aa = new A(array("one", "two", "three"));
echo $aa;

$ar = new A("baz");
echo $ar;

$ax = new A($x);
echo $ax;

$ay = new A($y);
echo $ay;

Wynik:

Array#3
baz
Xfoo
Ybar

Zamiast kończącego wyjątku, jeśli nie znaleziono konstruktora, można go usunąć i zezwolić na" pusty " konstruktor. Czy jak chcesz.

 2
Author: galmok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-20 08:41:56

Dla php7 porównuję również Typ parametrów, można mieć dwa konstruktory o tej samej liczbie parametrów, ale innego typu.

trait GenericConstructorOverloadTrait
{
    /**
     * @var array Constructors metadata
     */
    private static $constructorsCache;
    /**
     * Generic constructor
     * GenericConstructorOverloadTrait constructor.
     */
    public function __construct()
    {
        $params = func_get_args();
        $numParams = func_num_args();

        $finish = false;

        if(!self::$constructorsCache){
            $class = new \ReflectionClass($this);
            $constructors =  array_filter($class->getMethods(),
                function (\ReflectionMethod $method) {
                return preg_match("/\_\_construct[0-9]+/",$method->getName());
            });
            self::$constructorsCache = $constructors;
        }
        else{
            $constructors = self::$constructorsCache;
        }
        foreach($constructors as $constructor){
            $reflectionParams = $constructor->getParameters();
            if(count($reflectionParams) != $numParams){
                continue;
            }
            $matched = true;
            for($i=0; $i< $numParams; $i++){
                if($reflectionParams[$i]->hasType()){
                    $type = $reflectionParams[$i]->getType()->__toString();
                }
                if(
                    !(
                        !$reflectionParams[$i]->hasType() ||
                        ($reflectionParams[$i]->hasType() &&
                            is_object($params[$i]) &&
                            $params[$i] instanceof $type) ||
                        ($reflectionParams[$i]->hasType() &&
                            $reflectionParams[$i]->getType()->__toString() ==
                            gettype($params[$i]))
                    )
                ) {
                    $matched = false;
                    break;
                }

            }

            if($matched){
                call_user_func_array(array($this,$constructor->getName()),
                    $params);
                $finish = true;
                break;
            }
        }

        unset($constructor);

        if(!$finish){
            throw new \InvalidArgumentException("Cannot match construct by params");
        }
    }

}

Aby go użyć:

class MultiConstructorClass{

    use GenericConstructorOverloadTrait;

    private $param1;

    private $param2;

    private $param3;

    public function __construct1($param1, array $param2)
    {
        $this->param1 = $param1;
        $this->param2 = $param2;
    }

    public function __construct2($param1, array $param2, \DateTime $param3)
    {
        $this->__construct1($param1, $param2);
        $this->param3 = $param3;
    }

    /**
     * @return \DateTime
     */
    public function getParam3()
    {
        return $this->param3;
    }

    /**
     * @return array
     */
    public function getParam2()
    {
        return $this->param2;
    }

    /**
     * @return mixed
     */
    public function getParam1()
    {
        return $this->param1;
    }
}
 1
Author: Serginho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-17 08:53:45

Hmm, dziwi mnie, że jeszcze nie widzę tej odpowiedzi, Załóżmy, że rzucę czapkę na ring.

class Action {
    const cancelable    =   0;
    const target        =   1
    const type          =   2;

    public $cancelable;
    public $target;
    public $type;


    __construct( $opt = [] ){

        $this->cancelable   = isset($opt[cancelable]) ? $opt[cancelable] : true;
        $this->target       = isset($opt[target]) ?     $opt[target] : NULL;
        $this->type         = isset($opt[type]) ?       $opt[type] : 'action';

    }
}


$myAction = new Action( [
    Action::cancelable => false,
    Action::type => 'spin',
    .
    .
    .
]);

Opcjonalnie możesz rozdzielić opcje na ich własną klasę, np. Rozszerzanie SplEnum.

abstract class ActionOpt extends SplEnum{
    const cancelable    =   0;
    const target        =   1
    const type          =   2;
}
 1
Author: Garet Claborn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-05 22:22:27

Bardziej nowoczesny aproach: Mieszasz oddzielne klasy w jedną, jednostkę i uwodnienie danych. Więc w Twoim przypadku powinieneś mieć 2 klasy:

class Student 
{
   protected $id;
   protected $name;
   // etc.
}
class StudentHydrator
{
   public function hydrate(Student $student, array $data){
      $student->setId($data['id']);
      if(isset($data['name')){
        $student->setName($data['name']);
      }
      // etc. Can be replaced with foreach
      return $student;
   }
}

//usage
$hydrator = new StudentHydrator();
$student = $hydrator->hydrate(new Student(), ['id'=>4]);
$student2 = $hydrator->hydrate(new Student(), $rowFromDB);

Należy również pamiętać, że należy użyć doktryny lub innego ORM, który już zapewnia automatyczne nawodnienie podmiotu. I powinieneś użyć dependency injection, aby pominąć mannualy tworzenie obiektów takich jak StudentHydrator.

 1
Author: YuraV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-25 19:30:11

W odpowiedzi na najlepszą odpowiedź Kris ' A (która zadziwiająco pomogła zaprojektować moją własną klasę btw), oto zmodyfikowana wersja dla tych, którzy mogą ją uznać za przydatną. Zawiera metody wybierania z dowolnej kolumny i zrzucania danych obiektu z tablicy. Zdrowie!

public function __construct() {
    $this -> id = 0;
    //...
}

public static function Exists($id) {
    if (!$id) return false;
    $id = (int)$id;
    if ($id <= 0) return false;
    $mysqli = Mysql::Connect();
    if (mysqli_num_rows(mysqli_query($mysqli, "SELECT id FROM users WHERE id = " . $id)) == 1) return true;
    return false;
}

public static function FromId($id) {
    $u = new self();
    if (!$u -> FillFromColumn("id", $id)) return false;
    return $u;
}

public static function FromColumn($column, $value) {
    $u = new self();
    if (!$u -> FillFromColumn($column, $value)) return false;
    return $u;
}

public static function FromArray($row = array()) {
    if (!is_array($row) || $row == array()) return false;
    $u = new self();
    $u -> FillFromArray($row);
    return $u;
}

protected function FillFromColumn($column, $value) {
    $mysqli = Mysql::Connect();
    //Assuming we're only allowed to specified EXISTENT columns
    $result = mysqli_query($mysqli, "SELECT * FROM users WHERE " . $column . " = '" . $value . "'");
    $count = mysqli_num_rows($result);
    if ($count == 0) return false;
    $row = mysqli_fetch_assoc($result);
    $this -> FillFromArray($row);
}

protected function FillFromArray(array $row) {
    foreach($row as $i => $v) {
        if (isset($this -> $i)) {
            $this -> $i = $v;
        }
    }
}

public function ToArray() {
    $m = array();
    foreach ($this as $i => $v) {
        $m[$i] = $v;    
    }
    return $m;
}

public function Dump() {
    print_r("<PRE>");
    print_r($this -> ToArray());
    print_r("</PRE>");  
}
 0
Author: James M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-01 21:44:06

Wywołanie konstruktorów według typu danych:

class A 
{ 
    function __construct($argument)
    { 
       $type = gettype($argument);

       if($type == 'unknown type')
       {
            // type unknown
       }

       $this->{'__construct_'.$type}($argument);
    } 

    function __construct_boolean($argument) 
    { 
        // do something
    }
    function __construct_integer($argument) 
    { 
        // do something
    }
    function __construct_double($argument) 
    { 
        // do something
    }
    function __construct_string($argument) 
    { 
        // do something
    }
    function __construct_array($argument) 
    { 
        // do something
    }
    function __construct_object($argument) 
    { 
        // do something
    }
    function __construct_resource($argument) 
    { 
        // do something
    }

    // other functions

} 
 0
Author: viral,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-02 14:31:26

Zawsze możesz dodać dodatkowy parametr do konstruktora o nazwie coś w rodzaju mode, a następnie wykonać na nim polecenie switch...

class myClass 
{
    var $error ;
    function __construct ( $data, $mode )
    {
        $this->error = false
        switch ( $mode )
        {
            'id' : processId ( $data ) ; break ;
            'row' : processRow ( $data ); break ;
            default : $this->error = true ; break ;
         }
     }

     function processId ( $data ) { /* code */ }
     function processRow ( $data ) { /* code */ }
}

$a = new myClass ( $data, 'id' ) ;
$b = new myClass ( $data, 'row' ) ;
$c = new myClass ( $data, 'something' ) ;

if ( $a->error )
   exit ( 'invalid mode' ) ;
if ( $b->error )
   exit ('invalid mode' ) ;
if ( $c->error )
   exit ('invalid mode' ) ;

Również z tą metodą w dowolnym momencie, jeśli chcesz dodać więcej funkcji, możesz po prostu dodać kolejny przypadek do instrukcji switch, a także możesz sprawdzić, czy ktoś wysłał właściwą rzecz - w powyższym przykładzie wszystkie dane są w porządku, z wyjątkiem C, ponieważ jest to ustawione na "coś" , a więc flaga błędu w klasie jest ustawiona i kontrola jest zwracana z powrotem do głównego programu, aby mógł zdecydować, co zrobić dalej (w przykładzie powiedziałem jej, aby wyszła z Komunikatem o błędzie "invalid mode" - ale alternatywnie można było ją zapętlić z powrotem, aż zostaną znalezione poprawne dane).

 0
Author: TheKLF99,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-29 06:27:30

Stworzyłem tę metodę, aby pozwolić jej używać nie tylko na konstruktorach, ale w metodach:

Mój konstruktor:

function __construct() {
    $paramsNumber=func_num_args();
    if($paramsNumber==0){
        //do something
    }else{
        $this->overload('__construct',func_get_args());
    }
}

Moja metoda doSomething:

public function doSomething() {
    $paramsNumber=func_num_args();
    if($paramsNumber==0){
        //do something
    }else{
        $this->overload('doSomething',func_get_args());
    }
}

Obie działają tą prostą metodą:

public function overloadMethod($methodName,$params){
    $paramsNumber=sizeof($params);
    //methodName1(), methodName2()...
    $methodNameNumber =$methodName.$paramsNumber;
    if (method_exists($this,$methodNameNumber)) {
        call_user_func_array(array($this,$methodNameNumber),$params);
    }
}

Więc możesz zadeklarować

__construct1($arg1), __construct2($arg1,$arg2)...

Lub

methodName1($arg1), methodName2($arg1,$arg2)...

I tak dalej:)

I przy użyciu:

$myObject =  new MyClass($arg1, $arg2,..., $argN);

Wywoła __constructN, gdzie zdefiniowałeś N args

Then $myObject - > doSomething ($arg1, $arg2,..., $argM)

It wywoła doSomethingM,, gdzie zdefiniowano M args;

 0
Author: jechaviz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-02 19:07:48