Seo Friendly Urls

I’m using php and Yii framework to create an web application but I`m stucked with some dynamic friendly URLs. I have the following scenario: in my view I have a form with a dropdown (where the user can select the SEASON) and two another hidden fields (eventID and playerName). When the user selects a season or click on the right panels (event or player) I submitted the form to the server with the selected values. Now what I want is to create the urls something like this:

www.domain.com/football/stats/season-name/(eventID)?/(player-name)?/ -> where (*)? 0 or 1 time e.g.


www.domain.com/football/stats/season-33/

www.domain.com/football/stats/season-33/91

www.domain.com/football/stats/season-33/arno-celestini

www.domain.com/football/stats/season-33/91/arno-celestini

Here is my view (h.t.t.p.://postimg.org/image/4r0xvgvw7/) and the view.php is:


<div id='main'>

 <div style="margin-left:50px;margin-top: 60px;width: 350px; border: 1px solid black; float:left;">

<?php $this->widget('zii.widgets.CBreadcrumbs', array(

    'homeLink' => CHtml::link('Home', Yii::app()->homeUrl),

    'links'=> $this->breadcrumbs));?><p>Season: <?php echo $selectedSeason;?> <br/>player:  <?php echo $selectedPlayer?> <br/>Id event: <?php echo $selectedEventId; ?></p>

    <?php echo CHtml::beginForm('', 'get', array('id' => 'filters_form', 'action' => $formURL));

        echo CHtml::dropDownList(

            'season',

            $selectedSeason,

            CHtml::listData($seasons, 'season_id', 'name'),

            array(

                'prompt' => 'Select a season',

                'onchange' =>"js:$('#filters_form').submit()"

            )

        );?>

    <input type="hidden" name="eventId" id="event_field" value="<?php echo $selectedEventId;?>" />

    <input type="hidden" name="playerName" id="player_field" value="<?php echo $selectedPlayer;?>" />

    <?php echo CHtml::endForm(); ?>

    <br/>

    <?php foreach ($matches as $match) { ?>

        <div class="match">

            <p><a href="<?php $this->createUrl('statistics/view', array('id' => $match->id, 'slug' => $match->match_date)); ?>">

            <?php echo $match->homeTeam->Name." <b>$match->home_goals - $match->away_goals</b> ".$match->awayTeam->Name; ?></a></p>

            <p><?php $match->match_date;?></p>

            <p><?php $match->match_type;?></p>

            <p><?php $match->home_goals;?></p>

            <p><?php $match->away_goals;?></p>

            <hr/>

        </div>

    <?php } ?>


</div>

<div id="vertical_filters" style="float:left;margin-top:60px;">

    <div class="filter_left" style="margin-left:20px;">

        <ul>

        <?php foreach ($events as $event) { ?>

                <li class="list-item">

                    <a class="event <?php if($selectedEventId == $event['id']) echo "selected";?>" href="<?php echo $event['id']; ?>"><?php echo $event['name']; ?></a>

                </li>

        <?php } ?>

        </ul>

    </div>

    <br/>

    <div class="filter_left" style="margin-left:20px;">

        <ul>

        <?php foreach ($players as $player) { ?>

                <li class="list-item">

                    <a class="player <?php if ($selectedPlayer == $player['id']) echo "selected"; ?>" href="<?php echo $player['name']; ?>"><?php echo $player['name'] . ' ' . $player['surname']; ?></a>

                </li>

        <?php } ?>        

        </ul>        

    </div>

</div>

<script>

    $(function() {

        console.log($('#filters_form').attr('action'));

        $('.event').click(function(e) {

            e.preventDefault();

            value = $(this).attr('href');

            $('#event_field').val(value);                

            $('#filters_form').submit();

        });


        $('.player').click(function(e) {

            e.preventDefault();

            value = ($(this).text() != 'All players')?$(this).text():'';

            $('#player_field').val(value);

            $('#filters_form').submit();

        });

    });

</script>

I tried in main.cfg to set a rule something like this:


'stats(/<season:\w+>)?(/<eventId:\d+>)?(/<playerName:\w+>)?' => 'statistics/index/',

but no success.

Hey,

Please verify your URL Pattern here: http://gskinner.com/RegExr/

Your Regex ([font="Courier New"]stats(/\w+)?(/\d+)?(/\w+)?[/font]) does not match your examples.

The character class \w does not contain the "-" character. So try this:


'stats(/<season:[\w-]+>)?(/<eventId:\d+>)?(/<playerName:[\w-]+>)?' => 'statistics/index/',

I modified the regex but no friendly-url. ohh…


class StatisticsController extends Controller

{

.....


	public function actionIndex($season = null, $playerName = null, $eventId = null)

	{

		Yii::app()->getClientScript()->registerCoreScript('jquery');

		//only dummy/unprocessed data;

		$seasons = Season::model()->findAll();

		$matches = Match::model()->with('homeTeam','awayTeam')->findAll();

		$criteria = new CDbCriteria;    

		$criteria->limit = 10;

		$events = EventType::model()->findAll($criteria);

		$players = Player::model()->findAll();

		

		$selectedSeason = Yii::app()->request->getQuery('season');

		$selectedPlayer = Yii::app()->request->getQuery('playerName');

		$selectedEventId = Yii::app()->request->getQuery('eventId');

		

		$url = $this->createUrl('statistics/index', array(

			'season' => $selectedSeason,

			'eventId' => $selectedEventId,

			'player' => $selectedPlayer,

		));

		echo $url;//it returns /football/35/90/Arno-Celestini---without stats in url?!?!

/* 


class MyRule extends CBaseUrlRule {

public function parseUrl($oManager, $oRequest, $sPathInfo, $sRawPathInfo) {

		$url = false;

		if (preg_match('%^(\w+)(/(\w+))?(/(\w+))?(/(\w+))?$%', $sPathInfo, $matches)) {

			if ($matches[1] === 'statistics') {

					$url = $matches[0];

			}

		}

		return $url;

	}


public function createUrl($oManager, $sRoute, $params, $sAmpersand) {		

		$url = false;

		if ($sRoute === 'statistics/index') {

			if (isset($params['season'], $params['eventId'], $params['playerName']))

				$url = $params['season'] . '/' . $params['eventId'] . '/' . $params['playerName'];

			else if (isset($params['season'], $params['eventId']))

				$url = $params['season'] . '/' . $params['eventId'];

			else if (isset($params['season'], $params['playerName']))

				$url = $params['season'] . '/' . '/' . $params['playerName'];

			else if (isset($params['season']))

				$url = $params['season'] . '/';

		}

		return $url;

  }

} 

....

in main.php:


'urlManager'=>array(

			'urlFormat'=>'path',

			'showScriptName'=>false,

			'rules'=>array(

				array('class' => 'MyRule'),

				'stats(/<season:[\w-]+>)?(/<eventId:\d+>)?(/<playerName:[\w-]+>)?' => 'statistics/index/',

				'statistics' =>'statistics/index',

				'<controller:\w+>/<id:\d+>'=>'<controller>/view',

				'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',

				'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',

			)


*/ 

.....

.....

		$this->render('index', array(

			'seasons' => $seasons,

			'matches' => $matches,

			'events' => $events,

			'players' => $players,

			'selectedSeason' => $selectedSeason,

			'selectedPlayer' => $selectedPlayer,

			'selectedEventId' => $selectedEventId,

			'formURL' => $url,

		));

	}

Please give us a working example of your code… When using CBaseUrlRule you need to implement the parseUrl() method to make URL’s work.

Also: The generated URL does not match the URL that you generate in MyRule::createUrl() (Where does the "football" string come from?)

Also you assign a parameter ‘player’ in the StatisticsController::createUrl() method, but in MyRule::createUrl() you check for a parameter ‘playerName’.

Please post the ‘components’ => ‘urlManager’ part of your config as well as related classes (such as a custom CUrlManager class and/or your CBaseUrlRule classes)

I edited the above(3rd) post .