2

In a controller, I am trying to load the model, but I have the following error:

Call to a member function getSearchURL() on bool

So the getModel() is returning false. This is the code of my controller, MycomponentController just extend BaseController:

namespace Example\Mycomponent\Site\Controllers;

class SearchController extends MycomponentController
{
    public function __construct($config = [])
    {
        parent::__construct($config);
    } 
   
    public function results()
    {
        $model = $this->getModel('Search');
        $this->setRedirect(
            $model->getSearchURL(
                'search',
                $model->getState('searchwords'),
                $model->getState('list.start'),
                $model->getState('list.limit'),
                $model->getUrlParams(),
                false
            )
        );
    }
}

The class MycomponentController is the following :

namespace Example\Mycomponent\Libraries\Controller;

use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;

class MycomponentController extends BaseController
{
    public function __construct($config = [], MVCFactoryInterface $factory = null, $app = null, $input = null)
    {
        $this->app      = Factory::getApplication();
    
        if (empty($this->input))
        {
            $this->input = $this->app->input;
        }

        parent::__construct($config, $factory, $app, $input);
    }
}

The model is named SearchModel.php and is the following:

namespace Example\Mycomponent\Site\Model;

class SearchModel extends MycomponentModel
{
    public function getSearchURL($view, $searchword = '', $limitstart = 0, $limit = 0, $params = '', $xhtml = true)
    {
    }
}

So why is the controller unable to find the model?

P.S.: I have found that it goes to Joomla\CMS\MVC\Factory\LegacyFactory::createModel() then her it call Joomla\CMS\MVC\Model\LegacyModelLoaderTrait::getInstance() but here it doesn't loads by namespace but by old way, because the Joomla\CMS\MVC\Model\LegacyModelLoaderTrait::getInstance() clean all the namepsapce by removing the \

3
  • From the shared info I think this question cannot be resolved (only by you), since to seeing why your controller does not find the corresponding model would take some more insight of the structure of your component. You are extending controllers and models in a non Joomla standard way and only you know why it is needed that way. All of the core components run without problems if the controller is working well. You can check Joomla4 components yourself how they call the models inside the controllers without any problem. i do not see any bug or problems in those references.
    – Zollie
    Commented May 17, 2021 at 14:35
  • I have investigated to see which method is called to loads the model. I have updated my post to relflect that Commented May 18, 2021 at 16:28
  • I think @Abhishek spotted the problem correctly with his answer, after you updated your question with valuable additional insights.
    – Zollie
    Commented May 18, 2021 at 17:13

3 Answers 3

2

MycomponentController class is missing the class prefix. It should be -

namespace Example\Mycomponent\Libraries\Controller;

use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;

class MycomponentController extends BaseController
{
    public function __construct($config = [], MVCFactoryInterface $factory = null, $app = null, $input = null)
    {
        $this->app      = Factory::getApplication();
    
        if (empty($this->input))
        {
            $this->input = $this->app->input;
        }

        parent::__construct($config, $factory, $app, $input);
    }
}

If it does not help, try by declaring the getModel method in the search controller class -

namespace Example\Mycomponent\Site\Controllers;

class SearchController extends MycomponentController
{
    public function __construct($config = [])
    {
        parent::__construct($config);
    } 
   
    public function results()
    {
        $model = $this->getModel('Search');
        $this->setRedirect(
            $model->getSearchURL(
                'search',
                $model->getState('searchwords'),
                $model->getState('list.start'),
                $model->getState('list.limit'),
                $model->getUrlParams(),
                false
            )
        );
    }
    
    public function getModel($name = 'Search', $prefix = 'Site', $config = array('ignore_request' => true))
    {
        return parent::getModel($name, $prefix, $config);
    }
}
1
  • the class declaration was right here in my file, i have just forgot it here. So yes, i will use a getModel() method in my controller like suggested Commented May 18, 2021 at 17:26
1

As far I am aware, feel free to correct me as I haven't played with Joomla 4 too much, the class naming conventions for controllers, models and views you need to use for Joomla to automatically resolve and load the related classes are the same as Joomla 3 and PSR/4 therefore your Controller and Model class name should be changed to class MycomponentControllerSearch & MycomponentModelSearch As per Zollie's comment the above does not apply to Joomla4

If you want to keep the names you have you need to tell Joomla where to find the Model, therefore you need to add your Models path to the list of paths to search. In Joomla 4 there is this method in the /libraries/src/MVC/Controller/BaseController.php that I think you are supposed to use

/**
 * Adds to the stack of model paths in LIFO order.
 *
 * @param   mixed   $path    The directory (string), or list of directories (array) to add.
 * @param   string  $prefix  A prefix for models
 *
 * @return  void
 *
 * @since   3.0
 */
public static function addModelPath($path, $prefix = '')
{
    BaseModel::addIncludePath($path, $prefix);
}

In your Controller you can use $this->addModelPath(JPATH_SITE . '/components/com_mycomponent/models' which seems to be the correct way from what I could see.

You could add a USE statement and call BaseModel::addIncludePath($path) directly like a lot of examples I found but it is depreciate in Joomla 5.0

1
  • In Joomla 4 you do not have to use the component’s name as prefix for the models and controllers, you just simply use the view name as the name as the OP correctly named the classes. His mistake is probably coming from somewhere else. For example, he might need to use the ‘Site’ or ‘Administrator’ prefix when he calls the model inside the controller and he should also extend the controller and model from the base classes standardly and could use `parent::getModel($name, $prefix); method (where $prefix = ‘Site’), if needed at particular models.
    – Zollie
    Commented May 15, 2021 at 10:28
0

I am also only taking my first steps in Joomla 4. Like Irata I think, that it is best to use the Joomla Standard.

Another possibility might be that your controller class extends

Joomla\CMS\MVC\Controller\AdminController;

or

Joomla\CMS\MVC\Controller\BaseController;

and overwrites the method getModel() so that the model is found.

1
  • My controller extends MycomponentController which already extends Joomla\CMS\MVC\Controller\BaseController; Commented May 15, 2021 at 20:52

Your Answer

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

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