How to handle errors from Model when JTable::store never returns errors?

967 views
Skip to first unread message

Clubnite

unread,
Oct 17, 2013, 12:52:32 PM10/17/13
to joomla-de...@googlegroups.com
Hi,

i noticed the JTable class never returning the error encountered by the DatabaseDriver class when it executes a query. Instead the Driver class throws a RuntimeException rather than returning it as an Exception object. The issue with this is, that sensitive database-internal information is revealed as the connection error is thrown 1:1. This way one has no chance to catch the error oneself, evaluate it and show a less verbose error to the user. So the code:

if (! $table->store())
{
   $this->setError($table->getError());
   return false;
}

is useless since $table->getError() will be empty.

Is this a bug?

Is this bad design?

Is this wanted?

How to work around this issue?

How do you guys work around this issue?

Michael Babker

unread,
Oct 17, 2013, 1:24:46 PM10/17/13
to joomla-de...@googlegroups.com
The use of getError(), setError(), and getErrors() (maybe one or two other methods) in the legacy MVC classes, JTable, and other top level classes still extending JObject is deprecated and discouraged.  In 3.x, we've been moving away from using JError (which those methods are really intended to be used with) and more towards PHP Exceptions.  A more suitable code block would be:
 
try
{
    $table->store();
}
catch (RuntimeException $e)
{
    // If you want to display the raw error message from the exception object
    JFactory::getApplication()->enqueueMessage($e->getMessage(), 'warning');
    return false;
 
    // If you want to display your own error
    JFactory::getApplication()->enqueueMessage('Your message here', 'warning');
    return false;
}


--
You received this message because you are subscribed to the Google Groups "Joomla! General Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to joomla-dev-gene...@googlegroups.com.
To post to this group, send an email to joomla-de...@googlegroups.com.
Visit this group at http://groups.google.com/group/joomla-dev-general.
For more options, visit https://groups.google.com/groups/opt_out.

Clubnite

unread,
Oct 17, 2013, 1:32:54 PM10/17/13
to joomla-de...@googlegroups.com
Thanks for your reply and the suggested solution.

Do i get you right that i can stop to write a bug to the bug tracker as this is no bug?

I am right that i am forced to duplicate the JModel::save method in all my JModel subclasses just for catching this error until you fully refactored this in the core?

Michael Babker

unread,
Oct 17, 2013, 1:38:03 PM10/17/13
to joomla-de...@googlegroups.com
It's a bug in that there are classes that need to be updated to not use those legacy methods and if they aren't behaving properly with the newer (PHP standard) code, they should be.
 
For your code, you can get around it for now by using this little snippet (using save as an example)
 
try
{
    parent::save();
}
catch (RuntimeException $e)
{
    // Error handling code
}


--

Clubnite

unread,
Oct 17, 2013, 1:45:34 PM10/17/13
to joomla-de...@googlegroups.com
Ok, i implemented this in my JTable subclasses and it works.

Thanks for the immediate support, Michael!

Matt Thomas

unread,
Oct 17, 2013, 1:46:15 PM10/17/13
to Joomla! General Development
Thanks for clarify this Michael. I was wondering about the use of try and catch blocks for this. Looks like I have some docs to update.

Best,

Matt Thomas
Founder betweenbrain
Phone: 203.632.9322
Twitter: @betweenbrain

Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted

Clubnite

unread,
Oct 18, 2013, 8:05:01 AM10/18/13
to joomla-de...@googlegroups.com
I just want to add that i'm pretty much confused by the various ways errors are handled within Joomla!. 
Meanwhile i cannot overseah anymore where to use JLog::add(), JError::raiseError(), throw Exception, setError(), enqueueMessage(). 

The suggested solution with the try/catch block in my JTable:store method in fact fixes the JModel::save problem mentioned. But it does not solve the problem with the last chain link - the JController::save method, where on error an additional message is added to JController::setError + JController::setMessage before returning to the view. This causes double output - one with error message and one without like:

Error

Duplicate entry.

Save failed with the following error: empty because no error message returned from JModel::save


The first two lines come the try/catch block in JTable::store, while the last line comes from JController::save.

To prevent me from duplicating code just to override 6 lines of unwanted behavior i combined your solution with the old behavior. Now the error is catched within the catch block and a customised message is set via setError(). This message properly arrives in JModel::save and from there to JController::save resulting in only one error message displayed.

Error

Save failed with the following error:
Duplicate entry.


I think it is time to clean this up and stay with one solution.

Richard Hellyer

unread,
Nov 1, 2015, 3:22:43 PM11/1/15
to Joomla! General Development
I am writing a cli script to insert articles in batches (Joomla 3.4.5) and came across this conversation.

I am using jtable, and try/catch.
However I noticed that if there is a duplicate alias, then $table->store() returns 'false' but does not trigger an exception.
Is this a correct behavior, or have I misunderstood how to catch the errors from $table->store ?

Richard
Reply all
Reply to author
Forward
0 new messages