php: эффективный запуск функций с одноразовыми загруженными классами несколько раз в необязательных файлах - PullRequest
0 голосов
/ 27 июля 2010

после прочтения ответов я переписал свой вопрос.

Допустим, у меня есть теоретическое php-приложение, которое использует объекты, которые делают разные вещи.Для каждой страницы, загружаемой приложением, будут запускаться разные сценарии.

Теперь я создал простой сценарий php, который создает простой объект.(все это выдумано, я просто пытаюсь понять это, прежде чем кодировать его)

$user = new userClass($db);
$user->login($credentials);

все хорошо, и я даже могу повторить процедуру несколько раз после создания пользовательского класса

$user = new userClass($db);
$user->login($credentials);
...
$user->login($credentials2);

Теперь представьте, если эти 2 части разделены на 2 разных файла php.

file1:
$user = new userClass($db);
$user->login($credentials);
file2:
$user->login($credentials2);

include file1
include file2

, если они выполняются по порядку, все в порядке, но если нет, или если file1 нетвключается вообще ...

file2:
$user->login($credentials);
file1:
$user = new userClass($db);
$user->login($credentials2);

include file2
include file1

тогда это не сработает ... они должны поддерживать порядок, поэтому давайте создадим основной php-файл, который загружается несмотря ни на что.

main file:
$user = new userClass($db);
file1:
$user->login($credentials);
file2:
$user->login($credentials2);

(например, включаемые файлы с автозагрузкой) включают в себя главный включаемый файл1, включающий файл2 или включают основной включаемый файл2, включающий файл1 или включают основной включаемый файл2

теперь файлы 1 и 2 можно загружать в любом порядке, а один независит от другого, но что, если и file1, или file2 не нужны?

main file:
$user = new userClass($db);
//nothing else gets loaded

, тогда основной файл также не нужен, и окажется, что это источник ресурсов, уверен, если его один класс - это не проблема,а что если главный файОн загружает сотни классов, которые никогда не привыкают?

совсем не элегантно.

Тогда давайте попробуем сделать это по-другому, давайте полностью удалим основной файл и сделаем это так (нижепример того, чего я хочу достичь):

file1:
if(!is_object($user)){
    $user = new userClass($db);
}
$user->login($credentials);
file2:
if(!is_object($user)){
    $user = new userClass($db);
}
$user->login($credentials2);

конечно, это работает, но не элегантно, не так ли?

давайте попробуем это с перегрузкой метода ...

class loader {
   private $objects;
   private $db;
   function __construct($db){
      $this->objects = array();
      $this->db = $db;
   }
   function __get($name){
      if(!isset($this->objects[$name])){
         return $this->objects[$name] = new $name($this->db);
      }
   }
}

main file:
$loader = new loader($db);
file1:
$loader->user->login($credentials);
file3:
$loader->user->login($credentials3);
file2:
$loader->user->login($credentials2);
file4:
$loader->user->login($credentials4);

, кажется, работает, пока вы не поймете, что больше не можете передавать объектам, созданным таким образом, любую другую переменную, кроме $ db.Это означает, что класс загрузчика ограничен для использования только с пользовательским классом (например), потому что использование класса загрузчика с любым другим классом потребует редактирования класса загрузчика

и простого сценария, подобного этому:

$user = new userClass($this->db);
$user->login($credentials);
$form = new formClass($_POST);
$form->process($info);

потребуется 2 отдельных класса загрузчика или как минимум 2 метода в классе загрузчика

   class loader {
       private $objects;
       private $db;
       function __construct($db){
          $this->objects = array();
          $this->db = $db;
       }
       function getuserclass($name){
          if(!isset($this->objects[$name])){
             return $this->objects[$name] = new $name($this->db);
          }
       }
       function getformclass($name){
          if(!isset($this->objects[$name])){
             return $this->objects[$name] = new $name($_POST);//just an unrealistic example.
          }
       }
    }

main file:
$loader = new loader($db);
file1:
$loader->getuserclass('user')->login($credentials);
file3:
$loader->getformclass('form')->process($info);

, но это тоже не элегантно.

Как это действительно должно быть сделано?

Ответы [ 3 ]

1 голос
/ 27 июля 2010

Это, вероятно, будет работать для вас:

class loader {
   private $objects;

   function __construct(){
      $this->objects = array();
   }

   function __call($name, $args){
      if(!isset($this->objects[$name])){
         return $this->objects[$name] = new $name($args);
      }
   }
}
$loader = new loader();

$user = $loader->user($db);
$form = $loader->form($form_args);

Если вы хотите иметь несколько экземпляров, вы можете включить дополнительный первый аргумент в каждый вызов loader, который является именем, и изменить код загрузчика, чтобы использоватьсначала аргумент в качестве ключа для объекта, а остальные передать конструктору объекта.

0 голосов
/ 14 августа 2010

просто используйте шаблон автозагрузки и синглтона: создайте класс, в который вы поместите все ваши классы (например, / modules /) с тем же именем файла, что и содержащийся в классе, помните ТОЛЬКО объявление.

теперь включите этокод (в «главном файле») поверх всех ваших страниц:

function __autoload($class_name) {
    if(!ctype_alnum(str_replace(array('-','_'), '',$class_name)))//filename check,security reasons
        die('Module name not valid! ');
    require_once 'modules/'.$class_name.'.php';//load the class
}

вы можете захотеть создать одноэлементный класс (это шаблон объекта, он в основном гарантирует, что существует только 1 сущность класса)

file: UserClass.php

<?php
class UserClass{
    private static $istance=null;
    private function UserClass($db){
        //your constructor code here
    };
    private static function getIstance($db){//you can call it init($db) and create a getInstace() that only return the instance,i prefer that way,do as you want.
        if($istance==null)
            $istance=new UserClass($db);
        return $istance;
    };
    function login($credentials){
            //....
    }
    //...other functions...
}
?>

Теперь, чтобы использовать его, вы можете просто сделать так:

require 'main.php';//require the autoloader
$user=UserClass::getIstance($db);//the class file will be automatically included and a new istance will be created
$user->login($credentials1);
$user->login($credentials2);
$user=UserClass::getIstance($db);//no new istance will be created,only returned
$user->login($credentials3);
$user2=UserClass::getIstance($db);//no new istance will be created,only returned
$user2->login($credentials4);

//Userclass($db);// don't use like that,it will give you ERROR(it's private like singleton pattern says)
0 голосов
/ 27 июля 2010

imo, именно поэтому использование include () через приложение является плохой идеей и может создать серьезные проблемы с обслуживанием.Особенно для людей, которые не знакомы с кодом.Они могут открыть файл PHP через два года и увидеть переменную ... и не имеют ни малейшего представления, что это такое и где он инициализируется.

Если вы столкнулись с подобной проблемой, возможно, базовая структура вашего приложениядолжен быть переделан.лучший способ организовать ваше приложение - поместить все включения в верхнюю часть приложения, чтобы не возникало двусмысленности относительно того, какие файлы включены или в каком порядке они включены.А затем используйте систему шаблонов для управления выводом.Не используйте «include ()» для вставки кода в строку.Используйте их вместо этого, как C включает.Ваши включенные файлы должны содержать функции и классы и очень мало кода, если он вообще есть, который работает в глобальной области видимости.

Сделайте это, и я думаю, вы обнаружите, что перестанете сталкиваться с подобными проблемами.

...