XF 2.0 How do you create an instance of an object from one class file to another?

Brad Padgett

Well-known member
I'm having issues with the following.

- I can't figure out how to carry over all my work in one class to the next.
- I can't find a way to create a new instance of an object in a separate class file

What I want to do is call functions from one class to another. I've tried require and even autoloading but when I add a function from the old class to the new one it keeps asking for "parameters" in the new object instance and alerts my phpstorm IDE for some reason.

I tried type-hinting (PHPDOC) my IDE but nothing worked so I'm thinking that I'm actually doing something wrong.

So my 2 questions:

- How do you create new instance of an object in a Xenforo 2 add-on class
- How do you add functions from one class to another (without declaring them static obviously)

Thanks for your help. I've been at it for a while and can't figure out why my IDE is being alerted from a new class instance that seemed perfectly fine. I tried /** @var myClass $variable */

But no luck on type hinting. Not sure why it's asking for parameters in a new class instance.
 
That's how namespaces work. When calling classes within a namespace, the scope will default to your local namespace unless you have explicitly declared otherwise.

PHP:
namespace Foo;

class Foo {
    public function __construct() {
      
    }
}
PHP:
namespace Bar;

class Bar {
    public function __construct(Foo $foo) {

   }
}

$bar = new Bar(new Foo());
This will throw out something like "Method __construct expects Foo as parameter 1, Bar/Foo given". Since you didn't declare Foo's usage explicitly, it will now be located in Bar's namespace. Thus, you need to declare it like:

PHP:
namespace Bar;
use Foo; // or Foo/Foo if you just need that one class

class Bar {
    public function __construct(Foo $foo) {

   }
}

$bar = new Bar(new Foo());
 
That's how namespaces work. When calling classes within a namespace, the scope will default to your local namespace unless you have explicitly declared otherwise.

PHP:
namespace Foo;

class Foo {
    public function __construct() {
     
    }
}
PHP:
namespace Bar;

class Bar {
    public function __construct(Foo $foo) {

   }
}

$bar = new Bar(new Foo());
This will throw out something like "Method __construct expects Foo as parameter 1, Bar/Foo given". Since you didn't declare Foo's usage explicitly, it will now be located in Bar's namespace. Thus, you need to declare it like:

PHP:
namespace Bar;
use Foo; // or Foo/Foo if you just need that one class

class Bar {
    public function __construct(Foo $foo) {

   }
}

$bar = new Bar(new Foo());

I get that. I'm aware that namespaces declare the root of the class but the issue that's arising is my IDE phpstorm is asking for required parameters when declaring the object. I'm not sure if there's a type hinting method I am not aware of. But it doesn't throw an error it just shows a yellow passive error and says it's requiring parameters.

Specifically my XFCP extended class version of \XF\Repository\SessionActivity which is asking for the parameter $em and $identifier in the class instantiation in my new class file which is the widget view model I setup for my add-on.

As of right now I've began using static functions to use functions inside other classes. Although you can't use "$this->" in the function since it's static so a better way would be good.

I also even used require_once('path/to/php/file') and the functions showed up in the IDE with a passive error saying it wasn't defined. I've been using namespaces and "use" the entire time.

My guess is this is a type hinting issue I have yet to discover how to get past. To be honest @var is the only one I really know how to use correctly from PHPDOCS currently. Anyways I appreciate the response regardless.

- Brad
 
Since you're extending the session activity repository in another add-on and attempting to use that extension, you're not truly extending it that way (there's no extension defined in the current add-on, thus no relation for PHPStorm to follow). The XF\Mvc\Entity\Repository expects $em and $identifier for the session activity repository.

activity.webp

mvcrepos.webp

You could try adding use XF\Mvc\Entity\Repository; to your extension code, but I doubt that would work.

You could also try extending your extended session activity from the new add-on and going from there.

Easiest way is probably to just duplicate your class extension in the new add-on.

However if the code is working properly when executed, the PHPStorm warning is one of those can can be ignored. (There are a ton of those in XF itself)

forum.webp
 
Last edited:
Perhaps paste some code so we can get an idea about what you're trying to do.

Have you been through the tutorial here: https://xenforo.com/xf2-docs/dev/lets-build-an-add-on/ ??

Yeah I've been going through it just about every day and no worries I believe I figured it out. It was like @Snog said. I need a type hint for XF\Mvc\Entity\Repository

Since you're extending the session activity repository in another add-on and attempting to use that extension, you're not truly extending it that way (there's no extension defined in the current add-on, thus no relation for PHPStorm to follow). The XF\Mvc\Entity\Repository expects $em and $identifier for the session activity repository.

View attachment 177872

View attachment 177873

You could try adding use XF\Mvc\Entity\Repository; to your extension code, but I doubt that would work.

You could also try extending your extended session activity from the new add-on and going from there.

Easiest way is probably to just duplicate your class extension in the new add-on.

@S Thomas @Sim @Snog

Do you think one of you guys could give an example of how to pull the entire user/guest record out of the database? Pulling the users out is easy and I have figured that out already but I want to also pull out the guest record out too. I'm trying to create a Most Users Ever Online add-on so what I'm wanting to do is find the users and guests in the database and then use a PHP function to count how many there are. Instead of extending the class I had originally done I'm now working on a method to simply count the database rows for users/guests. I think this is a much better method as I could simply count the entries. For users I could use the xf_user table bu what about guests? How could I pull out the guest records?

Thanks for the help. Either way I'll figure it out. I just thought one of you might have a method for this and would be willing to share your idea.

Regards,

Brad

However if the code is working properly when executed, the PHPStorm warning is one of those can can be ignored. (There are a ton of those in XF itself)

View attachment 177874

Yeah I figured it out and I appreciate your help. The new class instance needed a type hint for XF\Mvc\Entity\Repository and I was using a XFCP_ extended class extension via the admin panel.

Anyways I figured out I should probably not extend the SessionActivity Repository for the Most User Ever Online add-on even though it was meant for the users online counts.

Instead wouldn't it be best if I just pulled the online users and visitor records out of the database with a PHP function that would count the number of records? I think that would be a much better idea then trying to extend the class. So far I've got the controller to work and show the text below members online so that's a huge start.

What do you think guys? Best bet would probably be to pull the number of records out of the database for visitor and user? I think that's probably the best way to do it.

@S Thomas @Sim @Snog

Can one of you guys give an example of how I could pull the user/guest record out of the database to count the number of records for a Most Users Ever Online add-on? I've decided instead of extending that class, a better option would be to use a PHP function that could count the number of rows for users/guests that are currently online. Finding the function to do this won't be a problem. But how could I count the number of rows for users online? My personal idea is to use a new Class for this and use a count function to count the number of records in the xf_session_activity table but as the rows don't actually have an entry for it there may be a better way.

Thanks for your help guys. I just thought one of you may know.
 
Last edited:
Unless there are already functions for that, go for it. Otherwise no.

There are PHP built in functions for that but do you think if I pull the records out of xf_session_activity table it will work?

Currently if you look in that table you'll see all the columns but no entries. Is it true that users online have entries in that table? In other words when a user is online they get put in the table but is it a real entry? I could pull the records out of that table but would it be the same as doing it from a regular table.
 
Every online user and guest has an entry in that table.

Just extend the \XF\Repository\SessionActivity.php, grab the parent value for the getOnlineCounts function and compare that to your high count. If it's higher than your current high count, write it to your table (and the simple cache to avoid queries where possible) and return the parent value so other processes still have it available.

There are already enough add-ons running trivial functions that add database queries to the base XF query set when they aren't needed.
 
Every online user and guest has an entry in that table.

Just extend the \XF\Repository\SessionActivity.php, grab the parent value for the getOnlineCounts function and compare that to your high count. If it's higher than your current high count, write it to your table (and the simple cache to avoid queries where possible) and return the parent value so other processes still have it available.

There are already enough add-ons running trivial functions that add database queries to the base XF query set when they aren't needed.

Thanks for the tip. I'm glad you were able to share that with me. This shouldn't be too hard then.

I actually don't plan on extending anything for the back-end part at this point, especially base XF classes. I plan on making a class that doesn't extend anything at all and returning the number of entries in the table to writing them out to a new table named xf_mosteveronline. Then using that class on my XF\Widgets\MembersOnline view controller which places it right below the members online widget. I also plan to permission it completely and may even add separate entries for members and guest totals giving the user an option to choose which ones show. It should show totals for both members and guests and then a final total for all users based on what options you choose.

I'd rather not extend any class because as you said it's extra queries and to be honest it won't take very much code to pull out the number of entries in the table. I could then use the class inside my extension for XF\Widget\MembersOnline.

So that's basically my current plan as of now. I still don't know how long it will be before I release it. It could be a while depending on how long it takes me to setup but I do plan on making it a free add-on as it will be my first production. This will be a fairly simple add-on but I do plan to at least try to add options for members and guest counts... totals.. etc and it will be permissioned.

I'd rather not extend XF\Repository\SessionActivity.php because it's not needed to simply pull out the row counts and won't take much to do so. I could use it to return the counts in getOnlineCounts as I'm aware it's return value does give the counts but it would be much easier to simply use a built in php function that would count the amount of rows. I appreciate your help though a lot. Thank you.
 
There is no way to get the number of rows contained in a database table without querying the database that I know of. XenForo does that already in the repository. So, any other function will be adding at least one database query.
 
There is no way to get the number of rows contained in a database table without querying the database that I know of. XenForo does that already in the repository. So, any other function will be adding at least one database query.

Yes I agree. Just mentioning I imagine there will be less queries than if I extend XF\Repository\SessionActivity. I'm going to tinker with different methods but I think pulling out the number of rows would be the easiest and most painless method and then using that in my controller.

While I have you I have one more question and it's more than likely my last question. Instead of making a new thread since it's an easy question I wanted to ask it here.

For this controller extension example:

https://xenforo.com/xf2-docs/dev/controller-basics/#modifying-a-controller-action-reply-properly

^ Does that apply to only controller classes? Or must I use this on XF\Widget\MembersOnline

I don't think I'm supposed to use it when extending MembersOnline since I went that route instead of extending a base controller class. I just want to be sure. I found as @Sim mentioned in a private message where I asked him a question that using the widget directly was the best thing to do. As I had tried using the example on MembersOnline and it did not work. I think it's because it's not built as a controller type at all and couldn't accept the statement that was checking to see if it was a reply controller and instead it's a widget type.

Anyways @Snog I'm going to follow you now. Your very helpful and I really appreciate you actually taking the time to post that screenshot and writing out all that you have. This community is absolutely amazing.
 
Last edited:
I'd rather not extend any class because as you said it's extra queries and to be honest it won't take very much code to pull out the number of entries in the table. I could then use the class inside my extension for XF\Widget\MembersOnline.
You understood that wrong, it's exactly the opposite way. If you don't extend any classes but use your own, you still will have the base queries PLUS your own queries depending on what exact query you're talking about. Activate debug mode and add a &_debug=1 to any given page and you will see what queries already are being fired. And since many forums will have a classic Members online widget, this would add some unneeded overhead.
 
You understood that wrong, it's exactly the opposite way. If you don't extend any classes but use your own, you still will have the base queries PLUS your own queries depending on what exact query you're talking about. Activate debug mode and add a &_debug=1 to any given page and you will see what queries already are being fired. And since many forums will have a classic Members online widget, this would add some unneeded overhead.

Every add-on has at least some type of query. I doubt creating my own class is going to hurt anyone's amount of queries. I will try adding &_debug=1 to my page to check it out. All I plan to do as I've said is count the amount of rows in a single class for the xf_session_activity table and then use that class in XF\Widget\MembersOnline

I still think it's better than extending SessionActivity as when you extend a class your forced into changing that file rather than using brand new functions and I'd rather not have to work around manipulating another file when I don't need to. Also @S Thomas no worries I was talking to Snog.

This will be a fairly simple add-on but extending SessionActivity in order to get the return value from getOnlineCounts is not needed because it would require me to have to create a third file that would then end up causing extra queries all together. Where instead I may be able to do this with only a couple files, probably 3 at the most depending on the options and permissions I add.
 
I still think it's better than extending SessionActivity as when you extend a class your forced into changing that file rather than using brand new functions and I'd rather not have to work around manipulating another file when I don't need to.
You should read into OOP and why it's bad to re-use code.
This will be a fairly simple add-on but extending SessionActivity in order to get the return value from getOnlineCounts is not needed because it would require me to have to create a third file that would then end up causing extra queries all together. Where instead I may be able to do this with only a couple files, probably 3 at the most depending on the options and permissions I add.
You can create multiple classes and even multiple namespaces in the same file, if that really is something you're concerned about..
 
You should read into OOP and why it's bad to re-use code.

I agree with you. I am reading into it. I study it all the time. That's the point I was trying to make. I don't want to mess around with the members online widget by extending SessionActivity if I don't have to.

You can create multiple classes and even multiple namespaces in the same file, if that really is something you're concerned about..

Actually from reading the docs it says you can only have 1 class per file. Also I agree with everything you guys are saying, just trying to share with you what I plan to do instead of extending that file. I think it's more plausible than extending the file for members online.
 
One of the very first things you learn from OOP and why it's good is the principle of polymorphism, overriding in this case. You should read about that.

No clue where the docs say that, but that's not how php works. It might be that XF's autoloader works that way, but iirc that's not the case. Gonna look into that later. Files really should be just a physical help for humans to sort things and nothing more.
 
One of the very first things you learn from OOP and why it's good is the principle of polymorphism, overriding in this case. You should read about that.

No clue where the docs say that, but that's not how php works. It might be that XF's autoloader works that way, but iirc that's not the case. Gonna look into that later. Files really should be just a physical help for humans to sort things and nothing more.

Yeah it does say that about 1 class per file which is mainly why I made this thread regarding how to transfer my work from one class to another. But if you have a better way to make this add-on I'm open to hear your opinion.

I just imagine since xf_session_activity table only consist of members and guests that are online (at the time they are online for that matter) a simple solution to getting this add-on made would be to count the amount of rows in the table at the given time they are inserted which is during sessions. It actually works out great because if you look at the table it's completely empty. This is because from what I believe is true is it's based off of sessions instead of inserted rows. So I could get the number of rows and it "should" (though not completely sure) retrieve the amount of users online during each session. It's a realistic idea in my opinion and should work without a problem unless I'm missing something. Rather if I extended SessionActivity I'd be tampering with the members online widget code which is not necessarily needed IMO.
 
@Brad Padgett ... I suggest you spend some time downloading some free addons from some of the more well respected developers here and studying their code - learn how it works and try to understand why they did the things they did.

Don't forget that every time you store data using Simple Cache it causes a database write - reads are free (the entire cache is loaded every page load), but writes are not - so be sure you're not going to create unnecessary load by updating the cache frequently.
 
@Brad Padgett ... I suggest you spend some time downloading some free addons from some of the more well respected developers here and studying their code - learn how it works and try to understand why they did the things they did.

Don't forget that every time you store data using Simple Cache it causes a database write - reads are free (the entire cache is loaded every page load), but writes are not - so be sure you're not going to create unnecessary load by updating the cache frequently.

Thank you @Sim I've actually been studying the code for all sorts of add-ons that I have either downloaded for free or purchased in the past.

Do you have any suggested methods I can use to limit the amount of cache updating on the xf_session_activity write to my new table xf_mosteveronline?

How could I go about setting a read on the data without writing it out to the new table? I'm interested in adding a column rather than a new table if this were a preferred method but either way there has to be at least 1 write out for the counts unless you have a preferred method.

I propose the best method for this would be to use the CRON updating. Do you know where the CRON functions are stored in the Xenforo \src\XF files? I was actually planning to use the CRON for this once I found out how. You don't need to give me a huge explanation or anything, just if you would tell me where the source files for it are stored. I could easily set the CRON to update the cache automatically. Either way I will look for it.

You got a point there no worries I was planning on using the CRON for this. I'll check back and thank you
 
Top Bottom