5

I'm running Joomla 3.9.5 and I'm attempting to update my JFactory::getDbo() calls (which are deprecated) to the newer format using the container. However, I'm getting the following error: Call to undefined method Joomla\CMS\Factory::getContainer()

The code looks like

$db = \Joomla\CMS\Factory::getContainer()->get('DatabaseDriver');

which looks the same as what's being used in the deprecated method in \Joomla\CMS\Factory:

self::$database = self::getContainer()->get('DatabaseDriver');

What's the right way to get a DBO in the new containerized system?

1

4 Answers 4

6

Your issue comes solely from confusion about Joomla! versions. These facts should clear the air:

\Joomla\CMS\Factory::getDbo() is deprecated in 4.0 and will be removed in 5.0. It is alive and well in 3.9.

\Joomla\CMS\Factory::getContainer() doesn't exist in 3.9 as it was only added in 4.0.

The code you were looking at is from 4.0, not from 3.9.5.

In extensions compatible with 3.9 keep using \Joomla\CMS\Factory::getDbo(). Use \Joomla\CMS\Factory::getContainer() only in extensions compatible with 4.0 and above.

1
  • So it basically means that Factory::getDbo is becoming useless around 2024 :) what is the question in this topic?
    – Zollie
    Apr 15, 2019 at 14:01
8

If you are developing your extension only for Joomla 4.0+, you can replace

$db = Factory::getDbo();

with

$db = Factory::getContainer()->get('DatabaseDriver');
7

Joomla 3.9.x has a file public_html/libraries/classmap.php that contains all the old style Class names, and the new replacements. E.g.

JLoader::registerAlias('JFactory', '\\Joomla\\CMS\\Factory', '5.0');

JFactory is indeed deprecated. You can rewrite

// JFactory is deprecated
$db = JFactory::getDbo();

to

// Put at the top of your file 
use Joomla\CMS\Factory;

// Just remove the J 
$db = Factory::getDbo();

btw: sometimes the factory class has already been loaded and then you can just use

$db = $this->getDbo();

What IDE do you use? Some IDE software packages can help you finding the right classes.

I use PHPStorm (commercial software) together with CodeSniffer and the Joomla code standard. PHPStorm indicates all deprecated classes. When I click on CTRL + point the mouse on JFactory, my IDE gives a pop-up "alias JFactory of abstract class Factory". When I CTRL + click on JFactory, my IDE opens the classmap file with old/new Class names. To easily replace the JFactory with the new Factory name, I click on it, press ALT + ENTER and choose "Import Class", choose Joomla\CMS\Factory, and the correct Name Spacing is placed on top of my file.

3
  • Good answer @pe7er. You're going to fit in nicely here. I hope you continue to post comprehensive and insightful answers. (I like my PHPStorm too) Apr 14, 2019 at 22:24
  • The 5.0 is the version when this becomes deprecated, right? Apr 15, 2019 at 2:20
  • @mickmackusa I believe it will be deprecated in J4 and removed in J5
    – Lodder
    Apr 15, 2019 at 6:47
2

Your comment led me to doubt my belief that getDbo() is alive and well. I have tested my below techniques on Joomla3.9.5 and there are no problems.

Original answer...

Based on this documentation:

https://api.joomla.org/cms-3/classes/Joomla.CMS.Factory.html#method_getDbo

Returns the global \JDatabaseDriver object, only creating it if it doesn't already exist.

You should be able to use getDbo()`.

It would look something like this:

use \Joomla\CMS\Factory;  // at the top of your file
$db = Factory::getDbo();

or you can make the static call on the fully qualified namespace:

$db = \Joomla\CMS\Factory::getDbo();

Later answer...

Assuming your have set the DatabaseDriver in your container. Let's say something like:

$container = new Joomla\DI\Container;
$container->set('DatabaseDriver', Factory::getDbo());  // this is just what I used to set the driver

Then you merely fetch it like this:

$db = $container->get('DatabaseDriver');

I have tested $db to successfully allow queries on my local.

Some references:


To explain why I went to DI, I saw the following comment block in libraries/src/Factory.php:

/**
 * Global database object
 *
 * @var    DatabaseDriver
 * @since  11.1
 * @deprecated  5.0  Use the database service in the DI container
 */
public static $database = null;
5
  • Thanks, but the getDbo method is deprecated. I'm trying to get to the newer syntax using the container.
    – user101289
    Apr 14, 2019 at 4:15
  • 1
    @user101289 updated. I don't have any prior knowledge of Containers with Joomla, so I am going on this journey with you. Let me know if this doesn't solve where you are stuck. Apr 14, 2019 at 5:23
  • @user101289 - Factory::getDbo() method is not deprecated if you use \Joomla\CMS\Factory class, included on the top of your file. Link: api.joomla.org/cms-3/classes/…
    – Zollie
    Apr 14, 2019 at 5:33
  • You reckon that is the issue in the question, Zollie? Shall I just write use \Joomla\CMS\Factory; as the first line of my first snippet? Apr 14, 2019 at 5:34
  • 1
    @mickmackusa - yes, you were right in the first version of your answer.
    – Zollie
    Apr 14, 2019 at 5:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.