3

I'm trying to develop a Joomla 4 component and I almost completed it, but I have issues to save an item when the Alias is not Unique.

In the database, I've set up this:

CREATE UNIQUE INDEX aliasindex ON rwl35_rwlevents (alias); In the Model (administrator/components/com_rwlevents/src/Model), I have this:

protected function prepareTable($table)
{
    $date = Factory::getDate()->toSql();

    $table->name = htmlspecialchars_decode($table->name, ENT_QUOTES);
    $table->check();
    $table->generateAlias();

}

Then, in the EventTable.php file, (/administrator/components/com_rwlevents/src/Table)

I have this code:

public function check()
{

    try
    {
        parent::check();
    }
    catch (\Exception $e)
    {
        $this->setError($e->getMessage());

        return false;
    }
    // Check the publish down date is not earlier than publish up.
    if ($this->publish_down > $this->_db->getNullDate() && $this->publish_down < $this->publish_up) {
        $this->setError(Text::_('JGLOBAL_START_PUBLISH_AFTER_FINISH'));

        return false;
    }

    // Set publish_up, publish_down to null if not set
    if (!$this->publish_up) {
        $this->publish_up = null;
    }

    if (!$this->publish_down) {
        $this->publish_down = null;
    }

    $this->alias = trim($this->alias);
    if (empty($this->alias))
    {
        $this->alias = $this->name;
    }
    $this->alias = JFilterOutput::stringURLSafe($this->alias);
    return true;
}

Then, In the same file, I have a function to generate the Alias:

public function generateAlias()
{
    if (empty($this->alias))
    {
        $this->alias = $this->name;
    }

    $this->alias = ApplicationHelper::stringURLSafe($this->alias, $this->language);

    if (trim(str_replace('-', '', $this->alias)) == '')
    {
        $this->alias = Factory::getDate()->format('Y-m-d-H-i-s');
    }

    return $this->alias;
}

But in the Admin, when I try to save an item with an Alias that already exists in the Database, I have:

Duplicate entry 'concert-au-3-arena' for key 'aliasindex'

How can I code this to say: "if this Alias already exists, then, do this..."?

1 Answer 1

0

I finally "partially" solved this by moving a piece of code, and replacing the date by an increment :

    public function check()
    {

        try
        {
            parent::check();
        }
        catch (\Exception $e)
        {
            $this->setError($e->getMessage());

            return false;
        }

                // Check the publish down date is not earlier than publish up.
                if ($this->publish_down > $this->_db->getNullDate() && $this->publish_down < $this->publish_up) {
                    $this->setError(Text::_('JGLOBAL_START_PUBLISH_AFTER_FINISH'));

                    return false;
                }

                // Set publish_up, publish_down to null if not set
                if (!$this->publish_up) {
                    $this->publish_up = null;
                }

                if (!$this->publish_down) {
                    $this->publish_down = null;
                }

    jimport('joomla.filter.output');
    if (empty($this->alias)) {
        $this->alias = $this->name;
    }
    $pk = $this->id;
    if (empty($pk)) {
        $pk = 0;
    }

            $originAlias = $this->alias;

    $this->alias = EventHelper::stringURLSafe(trim($this->alias));

         if (empty($this->alias)) {
             $this->alias = $originAlias;
             $this->alias = EventHelper::replace($this->alias);
             $this->alias = JFilterOutput::stringURLSafe($this->alias);
         };

    $db = Factory::getDbo();
    $query = $db->getQuery(true);
          $query->select('COUNT(*)')
        ->from('#__rwlevents')
        ->where('`alias` = ' .$db->Quote($this->alias))
        ->where('`id` <> '.$pk);
    $db->setQuery($query);
            $newalias = $this->alias;
    $count = $db->loadResult();
            $increment = $count + 1;
            if (!empty($count) AND $count >= 1) {
             $this->alias = EventHelper::replace($newalias);
             $this->alias = JFilterOutput::stringURLSafe($newalias).'-'. $increment;
    }
    return true;
}

The only issue I have now is that when I have more than 1 Dupliacte, the Alias become something like this :

concert-au-3-arena-2-2

concert-au-3-arena-2-2-2

concert-au-3-arena-2-2-2-2

3
  • Instead of count, I would use ->select('MAX(id)'). Using count is not reliable when you delete items from your database.
    – pe7er
    Oct 25, 2022 at 7:08
  • @pe7er Thanks. But it seems my code runs a loop. Even if I use MAX instead of Count, then the 3rd duplicate is looking like this : concert-au-3-arena-1403-1404, when I would expect only concert-au-3-arena-1404 instead. Oct 25, 2022 at 20:49
  • 1
    My 2 cents: You can use MAX(id) + 1 directly in your select() method. Why do you declare $this->alias, then on the next line overwrite $this->alias? If you want to trim the potential trailing hypen&number, you can use preg_replace('/-\d+$/', '', $theString) or more directly preg_replace('/(?:-\d+)?$/', "-$newId", $theString) Oct 26, 2022 at 6:23

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.