我使用 PHP5 构建我自己的 MVC 框架。我有一种情况,我的所有 Controller 都在 Controller 命名空间中,如:
namespace Controllers
{
class Home extends \Framework\Core\Controller
{
...
}
}
在应用程序逻辑中,我需要从调用传递的 URL 中选择要调用的 Controller ,如下所示:
namespace Framework\Core;
class Application
{
protected $controllerName = 'home';
protected $methodName = 'index';
protected $controller;
public function __construct()
{
// Parse the received URL
$url = parseUrl();
// Choose the controller, if file exists
if (file_exists('../app/controllers/' . $url[0] . '.php'))
{
$this->controllerName = $url[0];
unset($url[0]);
}
require_once '../app/controllers/' . $this->controllerName . '.php';
// Call the controller
$objToCall = '\\Controllers\\' . $this->controllerName;
$this->controller = new $objToCall(); <<<======= PROBLEM HERE
... Proceed choosing the method and calling the objects method....
}
}
}
我的问题是:
我的 Controller 文件名为home.php,我的类名为Home(首字母大写)。所以上面的代码找不到/Controllers/home类,因为类是/Controllers/Home
另一方面,如果我从 Controller 中删除 namespace 并调用:
$this->controller = new $this->controllerName;
它工作正常,即使名称是 home....
我的问题:
a) 如果我不涉及命名空间,为什么 home 会被翻译成 Home?
b) 我怎样才能解决从 namespace 调用类而不需要知道其大写/小写条件的问题?
请不要建议将首字母更改为大写,因为我可能有 CustomerReceipt、PersonalCashWithdrawl 等类。
感谢您的帮助。
最佳答案
您可以做的是创建一个将文件与类匹配的数组。
/controllers/ 文件夹中的所有文件例如,如果您的文件夹包含:
关联数组将包含:
Key Value
-------------------- ----------------------------
home Home.php
recipefordisaster RecipeForDisaster.php
anothercontroller AnotherController.php
通过构建这种数组,您可以将类(无论大小写)与文件匹配。
灾难的秘诀
这将实现您想要的,但在我看来,这是灾难的根源。为什么 ?因为在某些操作系统(Linux、OSX 等)中,您可以将 home.php 和 Home.php 放在同一个文件夹中。您如何才能知道要使用哪个文件?提供的解决方案将不起作用,因为您显然不能为同一个键设置 2 个值。
您要考虑的另一件事是PHP 中的类不区分大小写。这就是 namespace 很重要的原因。这意味着以下代码可以完美运行:
class myclass {
public function printme() {
print 'hello world';
}
}
$a = new myclass(); // Correct case
$a->printme();
$b = new MyClass(); // "Incorrect" case... but still working
$b->printme();
建议的解决方案
我确实认为您应该将类名大小写与文件相匹配。这样,您将避免潜在的冲突并确保您不会错误地将类映射到错误的文件。
我不是建议你把第一个字母改成大写,我是建议你严格使用类提供的大小写来找到正确的路径。
开发人员应该知道:如果您输入的类名不正确(即不区分大小写),您就不能指望自动加载器能够正常工作。
路由
大多数框架可以进行自动路由,但也提供进行手动路由的可能性。您可以添加一个路由模块,允许开发人员“覆盖”默认路由。通过这样做,您将取悦那些想要尊重您的标准的人以及那些想要按照他们的方式行事的人。
结论
您的问题似乎很简单。但是,实际上,如果您希望它灵活而避免严格,您将不得不考虑很多事情。
您还可以像这样混合此答案中提供的策略:
问题仍然存在:您希望它变得那样灵活吗?你的电话...
关于带有变量名和命名空间的 PHP 类名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32015751/
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
当我在我的Rails应用程序根目录中运行rakedoc:app时,API文档是使用/doc/README_FOR_APP作为主页生成的。我想向该文件添加.rdoc扩展名,以便它在GitHub上正确呈现。更好的是,我想将它移动到应用程序根目录(/README.rdoc)。有没有办法通过修改包含的rake/rdoctask任务在我的Rakefile中执行此操作?是否有某个地方可以查找可以修改的主页文件的名称?还是我必须编写一个新的Rake任务?额外的问题:Rails应用程序的两个单独文件/README和/doc/README_FOR_APP背后的逻辑是什么?为什么不只有一个?
我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use
我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。
如何在Ruby中获取BasicObject实例的类名?例如,假设我有这个:classMyObjectSystem我怎样才能使这段代码成功?编辑:我发现Object的实例方法class被定义为returnrb_class_real(CLASS_OF(obj));。有什么方法可以从Ruby中使用它? 最佳答案 我花了一些时间研究irb并想出了这个:classBasicObjectdefclassklass=class这将为任何从BasicObject继承的对象提供一个#class您可以调用的方法。编辑评论中要求的进一步解释:假设你有对象
我正在编写一个简单的静态Rack应用程序。查看下面的config.ru代码:useRack::Static,:urls=>["/elements","/img","/pages","/users","/css","/js"],:root=>"archive"map'/'dorunProc.new{|env|[200,{'Content-Type'=>'text/html','Cache-Control'=>'public,max-age=6400'},File.open('archive/splash.html',File::RDONLY)]}endmap'/pages/search.
我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty
当我创建一个Rails应用程序时,控制台:railsnewfoo我的代码可以使用字符串“foo”吗?puts"Yourapp'snameis"+app_name_bar 最佳答案 Rails.application.class将为您提供应用程序的全名(例如YourAppName::Application)。从那里您可以使用Rails.application.class.parent获取模块名称。 关于ruby-on-rails-应用程序的名称是否可以作为变量使用?,我们在StackOve