php:在可选文件中多次有效地运行具有一次性加载类的函数

发布于 2024-09-11 20:02:50 字数 3381 浏览 4 评论 0原文

阅读回复后我重写了我的问题。

假设我有一个理论上的 php 应用程序,它使用执行不同操作的对象。 对于应用程序加载的每个页面,将运行不同的脚本。

现在我制作了一个简单的 php 脚本来创建一个简单的对象。 (这都是编出来的,我只是想在编码之前理解这一点)

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

一切都很好,我什至可以在创建用户类后重复该过程几次

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

现在想象一下如果这两个部分被分成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 或者 包括主要 include file2

现在 file1 和 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);

但这也不优雅。

真正应该如何完成?

after reading the responses I have rewritten my question.

Let's say I have a theoretical php application that uses objects that do different things.
For every page that gets loaded by the application, different scripts will be run.

now I made a simple php script that creates a simple object.
(this is all made up, I'm just trying to understand this before I code it)

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

all is fine, and I can even repeat the procedure several times after creating the user class

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

now imagine if these 2 parts are split in 2 different php files.

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

include file1
include file2

if they are run in order all is fine, but if they are not, or if file1 is not included at all...

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

include file2
include file1

then it won't work... they have to maintain order, so lets make a main php file that gets loaded no matter what.

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

(included files with autoloading for example)
include main
include file1
include file2
or
include main
include file2
include file1
or
include main
include file2

now file1 and 2 can be loaded in any order, and one does not depend on the other, but what if both file1 or file2 are unnecessary?

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

then the main file is also unnecessary, and will prove to be a resource hog, sure if its one class it's no problem, but what if the main file loads hundreds of classes that never get used?

not elegant at all.

Then let's try to do it another way, let's scrap the main file completely and do it like this (below is the bare bone example of what I want to achieve):

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

sure, it works, but it's not elegant, now is it?

let's try it with method overloading...

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);

seems to work, until you realize that you can no longer give any of the objects that are created this way any other variable except $db.
This means that loader class is limited to use with user class only (for example)
because using loader class with any other class will require editing of the loader class

and a simple script like this:

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

will require 2 separate loader classes or at least 2 methods in the loader class

   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);

but this is not elegant either.

How is this really supposed to be done?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

甜嗑 2024-09-18 20:02:50

这可能对您有用:

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);

如果您想要多个实例,您可能可以在每次调用加载器时包含一个额外的第一个参数(即名称),并更改加载器代码以使用第一个参数作为对象的键,然后传递剩下的交给对象的构造函数。

This would probably work for you:

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);

If you want multiple instances you could perhaps include an additional first argument in each call to loader that is a name, and change the loader code to use the first arg as a key for the object, and pass the rest to the object's constructor.

青萝楚歌 2024-09-18 20:02:50

在我看来,这正是为什么通过应用程序使用 include() 是一个坏主意的原因,并且可能会造成严重的维护麻烦。特别是对于不熟悉代码的人。他们可能会在两年后打开一个 PHP 文件并看到一个变量......并且不知道它是什么或它在哪里初始化。

如果您遇到此类问题,您的应用程序的基本结构可能需要重做。组织应用程序的更好方法是将所有包含内容放在应用程序的顶部,这样就不会不清楚包含哪些文件或包含它们的顺序。然后使用模板系统来控制输出。不要使用“includes()”内联插入代码。使用它们更像是 C 包含。您包含的文件应该包含函数和类,以及在全局范围内运行的很少(如果有的话)代码。

这样做,我想您会发现您将不再遇到此类问题。

imo, this is exactly why using include() through an app is a bad idea, and can create serious maintenance headaches. Especially for people who are unfamiliar with the code. They may open a PHP file two years from now and see a variable... and have no idea what it is or where it is initialized.

If you are encountering this sort of problem, your app's basic structure probably needs to be redone. a better way to organize your app is to put all includes at the top of your app, so that there's no ambiguity about what files are included, or the order that they are included. And then use a templating system to control output. Dont use 'includes()' to insert code inline. Use them instead more like C includes. Your included files should house functions and classes, and very little, if any code, that runs in the global scope.

Do that, and I think you'd find that you'll stop encountering these sort of problems.

扛起拖把扫天下 2024-09-18 20:02:50

只需使用自动加载器和单例模式:
创建一个类,将所有类(例如 /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 个实体)

文件: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)

simply use the autoloader and singleton pattern:
create a class where you put all your classes(for example /modules/ )with the same filename as the contained class,remember ONLY the declaration.

now include this code(on a "main file")on top of all your pages:

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
}

you may want to create a singleton class(it's a object pattern,it basically ensure that only 1 entity of the class exists)

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...
}
?>

now to use it you can simply do like so:

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文