So, I have a few classes I'm trying to use PHP's namespaces with and am having some trouble accessing the functions in the lowest level class.
Here's how it's laid out...
Activity -> Post
Activity has a namespace of activity and Post has a namespace of post
At the top of my Post class I have this code.
namespace Post;
use activity\activity;
That's the code that PHPStorm created when I made my class file and then extended my Activity class.
So, when I try to access my public functions inside Post, I have tried both of these methods...
\activity\post::function();
AND
$post = new \activity\post();
$post->function();
But PHPStorm tells me neither of those exist.
So, what's the actual way to access these lower level functions?
I've googled quite a bit but apparently I'm not searching for the right thing because I haven't found anything about sub classes.
Thanks so much for your help in understanding how this works.
Don't use \activity, use activity.
\activity is using the \ (or base) namespace.
Use doesn't extend a class, it creates an alias. Since you have Use activity\activity this makes it so you can access functions in the activity class by running activity::function() rather than using the full namespace \activity\activity::function().
You can also define use \activity\activity as test and access functions like test::function().
I'm not sure of the point of having the namespaces the same name as the classes though but sjagr addressed that in comments.
Related
I'm a beginner to L5. I read the documentation about extending classes but i didn't find any information about where to put the file in which i extend the class.
**I have to extend Str.php class. I have read that in L4 it had to be done by putting that file under App/folder but i didn't find that folder in L5.
So please can you tell me how can i do that?
This is the information i have now:
First, you must find where the class file is. We will be extending the Str class, which is under vendor/laravel/framework/src/Illuminate/Support. Note that you can also find this class under the aliases key in app/config/ app.php.
Now create a new folder called lib under app/folder. This folder will hold our class extensions. Because the Str class is grouped under the folder Support, it is suggested that you create a new folder named Support under lib too.
Now create a new file named Str.php under app/lib/Support, which you've just created:
But this is for L4
That's more of a general PHP question and there are two parts: 1) How to extend a class and 2) where to put files.
1) Extending classes isn't something Laravel or anyone else provides. That's right there in the language:
class A {}
class B extends A {}
As long as class A exists and is available, then class B can extend from it.
2) Where the files are is also important here. If you're defining class B and want to extend class A, the php runtime needs to know where to find A. Usually class A isn't defined in the same file as class B.
There are many ways to do this. You could require or include class A when you define class B. That would look something like:
a.php
class A {}
b.php
require "a.php";
class B extends A {}
Now with a lot of files like in the Laravel framework or any worthy library, you're going to have a lot of files to include and have to keep track of how to include those files. That's no fun. So, instead of doing that, PHP has provided a way to autoload the classes. That is, if you define classes in a predictable way, PHP can figure out what classes you're talking about without you having to use require or include statements.
There are also many ways of autoloading php files. In Laravel (and many, many other projects), the composer autoloader is used.
This means that files have to be placed in a pre-defined way in order for the composer autoloader to find them. By reading about the composer autoloader and then digging into the code to see how Laravel's classes are autoloaded, you'll be able to figure out how that happens.
Despite the intricate detail of Peter's answer, I figured I'd write something much more concrete: it doesn't matter.
If you check composer.json, you'll see that we are autoloading everything that is placed inside the app directory anyway. Hence, the choice is really yours. All that matters is that you maintain a sensible and readable structure. For example, you could place it in app/Lib, and namespace all your classes App\Lib (if App is your base namespace of course, which can be changed with php artisan app:name). Of course, you could also have a folder like Helpers/Lib for your extended classes, and keep some form of helpers.php with global helper functions in Helpers.
Why would you do this? Well, you might want to have an easy way to call your new Strfunctions, so instead of having to do Str::yourNewMethod($argument) everywhere, you could add a helper function yourMethod($argument) to easier call the function (if you intend to use it extensively).
One thing you have to remember though, as mentioned by Peter, is that the class you are extending won't automagically be found. It will, however, be autoloaded. Hence, to reference it you have to remember to namespace it, such as in the example below.
<?php namespace App\Helpers\Lib
Class Str extends \Illuminate\Support\Str {}
Also remember to namespace correctly when you call your own class.
I was wondering if it's possible to use a static PHP class (or a method of that class, should I say) without calling it via the namespace ala laravel?
I realise this is conflicting with the nature of namespaces, but I was mainly wanting to use them the same as Laravel does, where I can just call Example::method('test') rather than \example\example\Example::method('test')
At the top of your file, declare a use statement which creates an alias:
use example\example\Example;
Example::method('test'); //resolves to example\example\Example::('test')
You can even use a different name with 'as':
use example\example\Example as MyAlias;
MyAlias::method('test'); //resolves to example\example\Example::('test')
See http://php.net/manual/en/language.namespaces.importing.php for more information.
Note: This is not how laravel facades work but I think it is what you are looking for. If you want something more automatic then aliasing you will have to incorporate some logic into your autoloader.
What are the best practices for extending a library in PHP?
I'm using the bshaffer OAuth2 library. In my code, I instantiate the library like this:
//// Start up the OAuth2 server
require_once('./oauth2-server-php/src/OAuth2/Autoloader.php');
OAuth2\Autoloader::register();
All of the OAuth2 classes are under the namespace starting like OAuth2\foo\bar. I am able to extend these classes without specifying a namespace for my own classes by giving them a unique name (which I prefer not to do). However, I would like to create my own namespace in order to keep the actual class names the same when extending them.
For instance, when I try to extend the Pdo class this way, it says 'class Pdo already instantiated'.
class Pdo extends OAuth2\Pdo {
}
So I tried it this way. In MyServer.php, I have:
<?php
namespace MyNS;
class Server extends OAuth2\Server {
}
?>
But then I get an error that the class MyNS\OAuth2\Server does not exist. Obviously, it doesn't, and I don't think you can go 'up' a level with namespaces like you can with directories.
I've spent a fair amount of time reading the docs for PHP classes. I can extend the classes by renaming them (eg MyServer or MyPdo), but this seems messy and I feel like I should use my own name space. Or even MyNS\OAuth2 could work if I knew how to do it that way. Maybe I have to create my own autoloader for the classes (which I don't know how to do yet)?
Can someone please shine a light in my brain?
You were almost there with your own namespace - you just need an extra backslash \ to ensure that you are referring to the OAuth2 that is sitting in the global space. - i.e.
<?php
namespace MyNS;
class Server extends \OAuth2\Server {
// ^______________________ here
}
I am writing a PHP extension in C, and I would like to put the classes, functions, and variables I am creating in a namespace. I have not been able to find anything in the extension documentation regarding namespaces. To be clear, I want the equivalent of
namespace MyNamespace{
class MyClass{
}
}
but in a C extension. More specifically, I am looking for a function or macro in the Zend C API that allows me to assign a PHP namespace to a class or function I have written in C. Is this possible?
Putting a class in a namespace is very simple. Where normally you would initialize a class with
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "MyClass", my_class_methods);
instead write the second line as
INIT_CLASS_ENTRY(ce, "MyNamespace\\MyClass", my_class_methods);
The namespace does not need to be included in the method declarations or in the members of the my_class_methods array to properly match them with the class.
To use Namespaces in PHP extensions, you are basically just putting a prefix in front of the class or function name.
I'm not really a PHP internals developer, so the specifics are not entirely clear to me how this works, unfortunately there is very, very little information online that I could find about this as well (I really put Google through it's paces), and the article below is the best I could find.
However, it seems this article hints at the correct solution, which seems to be, that when you register the function with the Zend engine/PHP internals, you do so like "myNS\\MyFunc" and it should then be accessible from the myNS defined there. I would try out a few different variations with this, and see how far that gets you.
Your best option would be to ask in #php-internals on Freenode (if you can get an invitation) or on the PHP Mailing list.
If you manage to find a solution, the Internet seems to be in need of a good article on how one would accomplish this.
Source http://www.php-cpp.com/documentation/namespaces
A namespace is nothing else than a class or function prefix. If you want your classes or functions to appear in a specific namespace, you simply have to add a prefix to the class or function name....
Update: I've updated my answer to try to be more clear. I'm sorry it took so long, I originally replied from my Phone while I was traveling, with every intention of coming back and responding to your original comment, but I genuinely forgot about it until I got a notification from SO about comments. My apologies.
On a web project there are two classes that have the same name. This was never an issue until now, because the two classes where never used at the same time / in the same script.
Now we require to use both classes in one script, and therefor got ourselves an "Cannot redeclare class" fatal error.
My question is: What options are there to resolve this issue?
The one possible solution would be to rename one of the classes in question, but it is something I would very much like to avoid - one of the classes is part of a third-party software that should not be modified at this level, to remain updateable.
I know there are namespaces - are they a valid option to this problem? I have never used namespaces until now.
Assuming we would put one of the classes into a namespace: Would this resolve the issue? Also, what measures would we need to take to access the now-namespaced class?
Namespaces would surely solve your problem.
For example I got multiple classes named 'core', but because they're all classes of a different namespace it doesn't give any conflict at all.
This does mean you have to go over all your code and refer to the namespaced class with the correct path.
$item = new doubleClass();
would become
$item = new \my_namespace\doubleClass();
Also make sure that your other scripts don't get namespaced otherwise it wouldn't be able to find the non namespaced class anymore.
How Namespace work:
consider we have 2 classes named User in file structure
/Package1/User.php
with content
<?php
namespace Package1;
class user {...}
and
/Package2/User.php
with content
<?php
namespace Package2;
class user {...}
and now for some reason we decide to use both in some class UserManager in:
/Package3/UserManager.php
with content:
<?php
namespace /Package3;
use package1/User as User1;
use package2/User as User2;
class UserManager {
public function __construct(User1 $user1, User2 $user2) {...}
...
}