Welcome, Guest
Username: Password: Remember me

TOPIC: SEF and components

SEF and components 06 Oct 2015 12:46 #13571

  • MorganL
  • MorganL's Avatar
  • Offline
  • Platinum Member
  • Posts: 438
  • Thank you received: 53
  • Karma: 15
How can I control the SEF for a J-Cook created component?

I have a table called deals, with individually named items.

When I create a menu pointing at the collection view its fine
http://(domain)/deals

However when I click on a deal it returns
http://(domain)/deals/deal/deal?cid[0]=1

Ideally I would prefer
http://(domain)/deals/($this->item->dealname) i.e http://(domain)/deals/free-beer-2015

Or at a push
http://(domain)/deals/deal/free-beer-2015

Anyone know how to get me started on the implementation of this so I can at least improve on the default?
Morgan Leecy MCSE

Novell / Linux
PHP. MYSQL, Apache, node.js
Coldfusion, JQuery, HTML5
Joomla
The administrator has disabled public write access.

SEF and components 06 Oct 2015 15:42 #13572

  • admin
  • admin's Avatar
  • Offline
  • Administrator
  • Chef
  • Posts: 3711
  • Thank you received: 987
  • Karma: 140
I am not expert in that, but I can give you a hint.

Edit router.php of your component. It contains the function to encode and decode the url params.
That's all I can say.
I always use the SEO of the menu system, and if it uses some filters, then they appears in clear. I never went so far in that.

Anybody can help ?
Coding is now a piece of cake
The administrator has disabled public write access.

SEF and components 06 Oct 2015 16:16 #13573

  • MorganL
  • MorganL's Avatar
  • Offline
  • Platinum Member
  • Posts: 438
  • Thank you received: 53
  • Karma: 15
Looks like I will be doing some reading later!

docs.joomla.org/Supporting_SEF_URLs_in_your_component
Morgan Leecy MCSE

Novell / Linux
PHP. MYSQL, Apache, node.js
Coldfusion, JQuery, HTML5
Joomla
The administrator has disabled public write access.

SEF and components 06 Oct 2015 19:47 #13576

  • Romkabouter
  • Romkabouter's Avatar
  • Offline
  • Elite Member
  • Posts: 310
  • Thank you received: 131
  • Karma: 48
First:
You will have to change router.php in your component's root.
You can not fork it.

Second:
You need to change YourcomponentBuildRoute and YourcomponentParseRoute
Let's start with YourcomponentBuildRoute.

Is starts with setting $segments = array();
That will be your array of segments (duh).
Check the function and it will be quite clear:
This code
	if(isset($query['view']))
	{
		$view = $query['view'];
		$segments[] = $view;
		unset( $query['view'] );
	}
check for the query view (you will see this when you have SEF turned off.
Your url will be something like:
http://(domain/)index.php?option=com_yourcomponent&view=deals&Itemid=117
==> Itemdid is the id of the active menu, the view is in this case "deals"
segments[] will only return "deals".

No, when selecting an item, your url will probably be someting like:
http://(domain/)index.php?option=com_yourcomponent&view=deal&layout=deal&cid[0]=1&Itemid=117

Rewriting this will become:
http://(domain)/deals/deal/deal?cid[0]=1 The first "deals" in the URL you pasted is because your menuitem is called "deals".
Breaking down you have for the menuitem http://(domain)/deals/
Then the view = deal, and after that layout = deal
So, there is only cid[0]=1 left to route.

If your deal has a name, you can do this by checking $query after the check for view and layout
	if (isset($query['cid'])) {
        $db = JFactory::getDbo();
        $dbQuery = $db->getQuery(true)
            ->select('name')
            ->from('#__yourcomponent_deals')
            ->where('id=' . (int) $query['cid'][0]);
        $db->setQuery($dbQuery);
        $name = $db->loadResult();
//some url thingy, you can change it or make it safer/better
		$segments[] = urlencode($name);
		unset( $query['cid'] );
	}
The, your url will be on the list:
http://(domain)/deals/deal/deal/free-beer-2015

Without the YourcomponentParseRoute, this will not work because YourcomponentParseRoute has no way of knowing what "free-beer-2015" has for id to look for in the database. Cook needs cid[].

Let's make it understand:
Go to the url http://(domain)/deals/deal/deal/free-beer-2015, it will probably give a nice page without your item
Lookup to the YourcomponentParseRoute function and do a var_dump of the segments:
var_dump($segments);
Then refresh and on top of the page you'll see: array(3) { [0]=> string(6) "deal" [1]=> string(10) "deal" [2]=> string(7) "free-beer-2015" }
The first entry is your view, the second the layout, the router.php has code for that in the YourcomponentParseRoute function

The third part is the one we need, is it the name of our item.
So, after the first to segment-checks do a check on the 3rd:
	if (isset($segments[$nextPos])) {
        $db = JFactory::getDbo();
        //get the id from name
        $dbQuery = $db->getQuery(true)
            ->select('id')
            ->from('#__yourcomponent_deals')
            ->where("name='" . $segments[$nextPos]."'");
        $db->setQuery($dbQuery);
        $id = $db->loadResult();
        //set the var needed by Cook
        $vars['cid'][0] = $id;
        //move to next segment
	$nextPos++;
	}

That is basically it.
You will probably need to do some rework so that the name will always get the correct id, maybe work add an alias wizard to your table and work with that.
That is safer. For items with the same name you will have no problem then.
You can also use the id as an extra segment:
http://(domain)/deals/deal/deal/1/free-beer-2015

Good luck!
The administrator has disabled public write access.
The following user(s) said Thank You: admin, MorganL

SEF and components 06 Oct 2015 22:59 #13577

  • MorganL
  • MorganL's Avatar
  • Offline
  • Platinum Member
  • Posts: 438
  • Thank you received: 53
  • Karma: 15
Brilliant explanation, look,forward to testing that tomorrow!
Morgan Leecy MCSE

Novell / Linux
PHP. MYSQL, Apache, node.js
Coldfusion, JQuery, HTML5
Joomla
The administrator has disabled public write access.

SEF and components 07 Oct 2015 07:42 #13578

  • Romkabouter
  • Romkabouter's Avatar
  • Offline
  • Elite Member
  • Posts: 310
  • Thank you received: 131
  • Karma: 48
You can also check the router.php in com_content, is had also some DB lookups, might be a good example

I did some tinkering last night, but alias is not a good idea.
I came across the following when I added an alias field to my table
- Alias was not unique, the alias of a item called "Document 1" became document-1 but when creating another "Document 1", that also got the document-1 for alias.
- When trying alias as segment, I got for some reason document:1 and not document-1, therefore the item could not be found in de DB.

I ended up using the id and using the title for seo purposed:
http://domain/records/record/20/document-1.html
The other document 1 got:
http://domain/records/record/22/document-1.html

Regards.
The administrator has disabled public write access.
The following user(s) said Thank You: admin

SEF and components 07 Oct 2015 11:27 #13582

  • admin
  • admin's Avatar
  • Offline
  • Administrator
  • Chef
  • Posts: 3711
  • Thank you received: 987
  • Karma: 140
Yes you are right, the mistake of Cook is to use cid[] in the url (inherited from old school way)
In the next release, this is deprecated. replaced by 'id'.
Coding is now a piece of cake
The administrator has disabled public write access.
Time to create page: 0.149 seconds

Get Started