Welcome to the Question2Answer Q&A. There's also a demo if you just want to try it out.
+4 votes
2.0k views
in Q2A Core by
Is there a way to do this?  I would like the question permalinks to look like this:

http://host.com/category/123/this-is-my-question

3 Answers

+1 vote
by

I'm afraid this would require changing the Q2A code in several places. The areas to focus on are function qa_q_request(...) in qa-base.php which builds the URL for a question, and qa-page.php which routes page requests to the appropriate qa-page-*.php file based on their path.

by
Thanks.  I looked at those two files and I could probably manage to make the changes myself.  Is there a way to make changes to core code without affecting my ability to get future upgrades?  Maybe by making my own plugin to make this behavior override the default?  Or is there a way I could contribute my changes into the core for a future release (open source model)?
+2 votes
by

There may have been a better way but here's how I did it.  Pretty easy to figure out.  Question2Answer code is extremely well written and easy to follow.  Great product!

First, in qa_base.php, add this to the end of function qa_q_request:

$category_result = qa_db_query_sub('SELECT a.tags FROM ^categories a, ^posts b WHERE b.postid=# and a.categoryid=b.categoryid', $questionid);

$category_slug = qa_db_read_one_value($category_result,true);
       
return $category_slug.'/'.(int)$questionid.'/'.implode('-', $words);

Next, in qa_page.php, replace the zero's with one's in this snippet.  This tells the request processor to look at the second value in the request parts to find question id.  The first part will be the category which can be ignored.

elseif (is_numeric($qa_request_parts[1])) {
        $pass_questionid=$qa_request_parts[1]; // effectively a parameter that is passed to file
        $qa_template='question';
        $qa_content=require QA_INCLUDE_DIR.'qa-page-question.php';
}

by
I tried your solution in qa_base.php. It worked, but as a side effect the RSS-feed is no longer working. I get a blank page and this error when loading the RSS-feed (located at yoursitename.com/feed/qa.rss ): "Called qa_db_escape() before connecting to database"

I solved it by adding a call to qa_base_db_connect(). The working code should be like this (I reused an already existing error handler, maybe a custom error handler should be written to make it "beautiful" =) ).

qa_base_db_connect('qa_feed_db_fail_handler');

$category_result = qa_db_query_sub('SELECT a.tags FROM ^categories a, ^posts b WHERE b.postid=# and a.categoryid=b.categoryid', $questionid);

$category_slug = qa_db_read_one_value($category_result,true);

qa_base_db_disconnect(); // disconnect as quickly as possible to free up resources

return $category_slug.'/'.(int)$questionid.'/'.implode('-', $words);
by
Ooops, seems that broke the reply function. :-( It still works to write replies and the reply is stored in database, but the "Called qa_db_escape() before connecting to database" error is shown after the reply is submitted.
Had to comment out the qa_base_db_disconnect(); to make replies work.
So now I use:
qa_base_db_connect('qa_feed_db_fail_handler');

$category_result = qa_db_query_sub('SELECT a.tags FROM ^categories a, ^posts b WHERE b.postid=# and a.categoryid=b.categoryid', $questionid);

$category_slug = qa_db_read_one_value($category_result,true);

return $category_slug.'/'.(int)$questionid.'/'.implode('-', $words);

This code probably leads to some inefficiency since the db connection is not disconnected, so I hope to get some hints how to solve this in a better way.
by
Don't worry too much about not explicitly disconnecting from the database - PHP will automatically do that when the script finishes executing anyway.
+1 vote
by

I know I am answering this quite late. However, if there is someone out there who is looking for the solution, this might help them. ( Version Q2A 1.7)

Here, below steps need to follow.

1) From admin dashboard: General -> URL Structure select the 1st Option.

2) Change the .htaccess file with below code.

Options -Indexes
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} libwww-perl.*
RewriteRule .* – [F,L]
#RewriteBase /
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php?qa-rewrite=$0&%{QUERY_STRING} [L]
</IfModule>

3) You need to handle incoming request + all the rendered URL in pages, sitemap, canonical URL, etc should be changed to the new format: <root_category>/<sub_category>/<question-id>/<question-title>. Create a plugin under qa-plugin folder (refer the url for how to create a plugin: http://docs.question2answer.org/plugins/overrides/). Following are the method overrides that need to be added in the plugin:

<?php
if ( !defined( 'QA_VERSION' ) ) { // don't allow this page to be requested directly from browser
        exit;
}

/*
    Handles the additional request format: 
    <root_category>/<sub_category>/<question-id>/<question-title>
    Base: qa-page.php
*/
function qa_get_request_content()
{
    $urlData = extract_request_url_data();
    if($urlData['is_question']) 
    {
        $userid = qa_get_logged_in_userid();
        $questionid = $urlData['question_id'];
        $question = qa_db_select_with_pending(qa_db_full_post_selectspec($userid, $questionid));
        $categoryBackPathFromDB = implode("/",array_reverse(explode("/",$question['categorybackpath'])));

        if($categoryBackPathFromDB == $urlData['category_back_path']) //Valid URL
        {
            global $qa_request;
            //set the global variable so that base function works correctly
            $qa_request = implode('/',qa_request_parts(2)); 
        }
    }
    return qa_get_request_content_base();
}

/*
    Appends category back path to question URL in the format: 
    <root_category>/<sub_category>/<question-id>/<question-title>
    Base: qa-base.php
*/
function qa_q_request($questionid, $title)
{
    $path = qa_q_request_base($questionid, $title);

    $userid=qa_get_logged_in_userid();
    $question = qa_db_select_with_pending(qa_db_full_post_selectspec($userid, $questionid));
    $explode_catBackpath = explode("/",$question['categorybackpath']);
    $reverse = array_reverse($explode_catBackpath);
    $categoryPath = implode("/",$reverse);

    return $categoryPath.'/'. $path;
}

function extract_request_url_data(){
    $requestparts = qa_request_parts();
    $urlData = array(
        'is_question' => false,
        'index' => 0,
        'question_id' => 0,
        'category_back_path' => ''
    );
    for($i = 0; $i < count($requestparts); $i++){
        if(is_numeric($requestparts[$i])){
            $urlData['is_question'] = true;
            $urlData['index'] = $i;
            $urlData['question_id'] = intval($requestparts[$i]);
            break;
        }
    }
    if($urlData['is_question'] && $urlData['index'] > 0){
        $urlData['category_back_path'] = implode('/', array_slice($requestparts, 0, $urlData['index']));
    }
    //var_dump($urlData);
    return $urlData;
}

Regards,

Vaibhav

...