I've got the following problem:
This is my super basic class:
class A
{
function foo()
{
echo "bar";
}
}
Now in front of the class declaration I use the following code:
$a = new A();
$a->foo();
When I open the php file in the browser, the output is "bar". Fine!
Now I want to do the same thing in another file.
directly in the first place I declare the following namespace:
namespace model\dbAction;
This is the path where my file with the class above is located.
So in another php file I do the following:
$a = new \model\dbAction\A();
$a->foo();
But I don't get any output and other code after that won't run so it looks like it breaks directly after the instancing of the class.
Any ideas why instancing the class in another file is not working?
Thanks!
Full code first php file:
<?php
namespace model\dbAction;
class A
{
function foo()
{
echo "bar";
}
}
Full code of the second file (which I call in the browser):
$a = new \model\dbAction\A();
$a->foo();
You still need to include the file -- providing the namespace itself will not include the file for you... unless you're using an autoloader. See: How do I use PHP namespaces with autoload?
Related
I'm new to PHP. When working with namespaces, I ran into a problem with RedBeanPHP.
I have php script "db.php":
namespace Fromtify\Database {
require_once('../libs/rb-mysql.php');
class Contoller
{
public function Connect()
{
R::setup(
#My database settings here...
);
if (!R::testConnection()) {
echo 'Cant connect to database';
exit;
}
}
}
}
My IDE(VSCode) tells me: "Undefined type 'Fromtify\Database\R"
How can I solve the problem?
Thank you in advance
When you use namespaces, PHP will assume that any class you load is under that namespace as well, unless you've imported it.
Example:
namespace Foo;
$bar = new Bar;
This will assume that Bar also is under the namespace Foo.
If the class you're using is under another namespace, or not in a namespace at all (the global namespace), you need to tell PHP which class to use by importing it. You do this with the use
namespace Foo;
use Bar;
$bar = new Bar;
So in your case, it should be:
namespace Fromtify\Database {
use R;
R:setup(...);
// The rest of your code
}
Side note!_
Unless you have multiple namespaces in the same file, which you usually don't have, there's not need for the syntax:
namespace Foo {
// your code
}
You can simpy do:
namespace Foo;
// Your code.
...which makes the code a bit cleaner.
You can read more about defining namespaces and using namespaces in the manual
Inside a method in my Model class, I include another PHP file. The code works until that included PHP file declares a class definition ie class Test123 {}.
The class name is unique. The only possible source of the issue that I could think of would be how I'm including a class within a class. However, I wasn't able to find information about this, so I assume it isn't a problem.
Any ideas?
//Inside of method inside of model class
include "{$_SERVER['DOCUMENT_ROOT']}/models/language.php";
I believe you're right in assuming that you can't declare a class inside a class, which is what you're essentially doing by including it inside a class method.
Could you perhaps do something like this?
class.php:
<?php
include("otherclass.php");
class MyClass {
public function run () {
$otherClass = new OtherClass();
}
}
otherclass.php:
<?php
class OtherClass {
}
index.php:
<?php
include("class.php");
$myClass = new MyClass();
$myClass->run();
I'm trying to autoload Classes, but I'm hindered by the scope. The Class is being loaded, but I'm using it out of scope. Here's the code to further explain what I'm trying to do.
AutoLoader.php
<?php
class AutoLoader {
private $namespace;
public function __construct($namespace) {
$this->namespace = $namespace;
spl_autoload_register(array($this, 'ClassLoader'));
}
private function ClassLoader($class) {
$class = "classes/{$this->namespace}/{$class}.php";
print("Loading class: {$class}");
include "{$class}";
}
}
?>
script.php
<?php
ini_set("display_errors", 1);
$loader = new AutoLoader("myspace");
$MyClassObj = new MyClass();
$result = $MyClassObj->MyClassFun();
?>
So when it comes down to script.php, I get the print out that it's loading the class and I don't get any errors that it can't find the file. So it looks like it's loading, but when I use the class to create a new object, it tells me it can't find the class. So I'm loading the include out of scope.
I included the AutoLoader in a separate file so I could load it into multiple files. Am I able to make this work or must the AutoLoader be part of script.php instead of separate?
edit: Including error, added error display to script.php.
Loading class: classes/myspace/MyClass.php
Fatal error: Class 'MyClass' not found in /usr/local/apache2/htdocs/scripts/script.php on line 5
edit: Including MyClass.php and directory structure
MyClass.php
<?php
class MyClass {
public function MyClassFun() {
$var = "hello world";
return $var;
}
}
?>
Directory Structure
htdocs/scripts/script.php
htdocs/classes/myspace/MyClass.php
htdocs/AutoLoader.php
If I change the class to MyClasse (misspelled) it will error on the include because it can't find the file. So using the proper MyClass I can only assume that it's finding the file since it's not producing an error. So the include looks good, but it still won't use it.
Which, now that I think about it more, is strange. The include is only occuring because of line 5 when I go to use the class. ClassLoader is being called by the spl_auto_register to search for the class. It's finding and including the class. Yet the same line 5 fails to actually use it.
I guess I don't understand that disconnect. Line 5 is properly calling the ClassLoader, but then fails to actually find the class once loaded.
I have a problem with including classes. Here's a simple example to explain the problem:
Class no. 1 (path: /home/day/Class_A.php):
class Class_A {
public function sayHi() {
echo "Good day";
}
}
Class no. 2 (path: /home/test/Class_B.php):
class Class_B {
public function greeting() {
if(class_exists("Class_A")!=true)
include "../day/Class_A.php";
$test = new Class_A();
$test->sayHi();
}
}
PHP file (path: /home/php.php)
if(class_exists("Class_B")!=true)
include "test/Class_B.php";
$g = new Class_B;
$g->greeting();
The problem is when php.php includes Class_B and Class_B includes Class_A, Class_B fails to open Class_B because the path of the object of the class is now the same as the php.php file.
My question is:
Is there a good and simple way to get around this?
Try changing:
include "../day/Class_A.php";
to
include dirname(__FILE__) . '/../day/Class_A.php';
This way, your include will be relative to the file that is doing the include (Class_B).
Looks like greeting is not a static function so you can't do:
Class_B::greeting();
You'd have to get a class B object and called greeting on it or add static to greetings declarations.
Second, why not uuse require_once? In php.php
require_once('test/ClassB.php');
And in ClassB.php:
require_once('../day/ClassA.php');
Use __autoload which is a magic function, that you define, that enables PHP to let you know when it doesn't have a class loaded, but that class needs to be loaded.
If you define the __autoload function like so,
function __autoload ($classname)
{
require('/path/to/my/classes/'.$classname.'.php');
}
you no longer need to add
require_once('/path/to/my/classes/MyClass.php');
into your files, because the first time that PHP encounters
$mine = new MyClass();
or
MyClass::staticMethodCall();
it will automatically call the __autoload function that you defined earlier.
__autoload('MyClass');
Resource: http://blog.samshull.com/2010/02/why-you-should-use-autoload-function-in.html
Would what mentioned in the title be possible? Python module style that is. See this example for what I exactly mean.
index.php
<?php
use Hello\World;
World::greet();
Hello/World.php
<?php
namespace Hello\World;
function greet() { echo 'Hello, World!'; }
Would this be possible?
Yes, have a look at the example of spl_autoload_register
namespace Foobar;
class Foo {
static public function test($name) {
print '[['. $name .']]';
}
}
spl_autoload_register(__NAMESPACE__ .'\Foo::test'); // As of PHP 5.3.0
new InexistentClass;
The above example will output something similar to:
[[Foobar\InexistentClass]]
Fatal error: Class 'Foobar\InexistentClass' not found in ...
Here is a link to a Autoloader builder, that
is a command line application to automate the process of generating an autoload include file.