Hi there,
There aren't that many differences and they're mostly two different ways of achieving the same result.
You are not required to use the $f3 instance as a parameter on your controllers and you can also use the same method of just calling "$f3 = \Base::instance()" as well.
Another thing that is also commonly done is to create a base class that your other classes extend, and on that class add a property for the F3 instance. Something like:
class SomeBaseClass
{
protected $f3;
public function __construct()
{
$this->f3 = \Base::instance();
}
// more common or shared properties or methods can also be in this class
}
And then have your other classes extend the SomeBaseClass which will give them access to $this->f3 which will be current the F3 instance.
But this is pretty much exactly the same as just calling $f3 = \Base::instance() whenever you need to access some F3 functionality.
You are also not required to use MVC with F3 so the framework makes it very flexible for developers to organize their classes, folder structure, etc in anyway they like so you have easy access to the F3 instance regardless of methodology.
The "instance()" method returns the current instance of a singleton class.
Other classes in F3 that also need to be singletons also inherit this instance() method to get their current instance.
For example:
$cache = \Cache::instance(); // gets the instance of the Cache class
$web = \Web::instance(); // gets the instance of the Web class.
And you can also create your own classes that extend the Prefab class and inherit this behavior (as you can read from the docs link above for the prefab class)
Sorry if my attempt at explaining this wasn't the most clear, I'm not a developer for F3 but have just used it for many years now so I'm pretty sure it's mostly correct but feel free to ask for any clarifications or more details.
Cheers