我想使用页面的slug路径作为URL(即:/ products / stereos / stereo-1 / info - 这只是直接跟在db中的页面树结构:info是stereo-1的子节点,立体声-1是立体声的孩子,等等。 (一切都将通过Pages控制器进行管理)。
我想的一种方法是做这样的事情:
// routes: (code found on another thread):
Router::connect('/:site/:language/:row:lastslash',array(
'controller' => 'posts', 'action' => 'parseURL',),
array(
'pass'=>array('row'),
'row'=>'.*?',
'lastslash'=>'\/?'
)
);
这应该将我转发到parseURL,其中包含$ row中的其余URL。进入parseURL后,我可以找到实际的帖子ID(通过使用slug路径),获取指定操作的db字段,然后转发到那里。理论上,系统应该处理数据库中的任何url树路径。例如:
/ page1 / page2 / page3 / info / thisPage - parseURL将遍历网址的每个部分,以查找“thisPage”的帖子ID。 'thisPage'将有一个'action'字段,指定要使用的操作,parseURL将重定向到那里。
有没有更好的方法来解决这个问题?
答案 0 :(得分:0)
这是一个棘手的问题。
我这样做的方法是在/app/tmp/cache/seo_routes.php中创建一个SEO路由文件,该文件会在每次请求时加载。
此路线文件由您附加到每个模型的SEO行为自动生成和更新。
它包含这样的行:
Router::connect('/content/about-us', array(
'plugin' => 'content',
'controller' => 'content',
'action' => 'view',
16));
这意味着当您制作新模型时,您只需将这些行添加到模型中:
/**
* @var actsAs A list of Behaviours to use
*/
public $actsAs = array(
'Seo'
);
每当您保存记录时,都会更新seo routes文件。
默认情况下,SEO行为会产生自己的slug,但您可以通过添加getSlug($ data)函数在模型中覆盖它。您需要在appModel中使用这些功能:
/**
* Returns the display name for this model with the data provided
* @param $data
* @return mixed
*/
public function getDisplayName($data){
$displayName = $data[$this->displayField];
return $displayName;
}
/**
* Gets the SEO slug (short title) for the item
* @param $data
* @return string
*/
public function getSlug($data){
$displayName = $this->getDisplayName($data);
$slug = $this->createSlugFromString($displayName);
return $slug;
}
/**
* Creates a slug from an input string
* @param $string
* @return string
*/
public function createSlugFromString($string) {
$slugParts = explode('.', $string);
foreach($slugParts as $slugIndex => $slugPart){
$slugParts[$slugIndex] = strtolower(Inflector::slug($slugPart, '-'));
}
$slug = implode('.', $slugParts);
return $slug;
}
在您的情况下,您将覆盖getSlug函数以返回所需的嵌套路径。
在你的seoBehavior中你需要这样的东西:
/**
* afterSave Callback
* Creates a new SEO record if required
*
* @param Model $model Model the callback is called on
* @param boolean $created Whether or not the save created a record.
* @return void
*/
public function afterSave(Model $model, $created) {
$modelPrimaryKey = $model->id;
// See if we already have an SEO record for this model record
$seoDetails = $this->seoModel->find(
'first',
array(
'conditions' => array(
'Seo.plugin' => $this->settings[$model->alias]['plugin'],
'Seo.model' => $model->name,
'Seo.foreign_key' => $modelPrimaryKey
)
)
);
if(empty($seoDetails)){
$modelData = $model->read(null, $modelPrimaryKey);
$slug = $model->getSlug($modelData[$model->alias]);
$title = $model->getDisplayName($modelData[$model->alias]);
$seoData = array(
$this->seoModel->alias => array(
'model' => $model->name,
'plugin' => $this->settings[$model->alias]['plugin'],
'foreign_key' => $model->id,
'action' => 'view',
'request_uri' => '/' . Inflector::underscore($model->name) . '/' . $slug,
'title' => $title,
'seo_attribute_type_id' => $this->defaultAttributeTypeId
)
);
// Create some default meta tags as well
$seoData['SeoMeta'] = array(
0 => array(
'key' => 'keywords',
'value' => ''
),
1 => array(
'key' => 'description',
'value' => ''
)
);
$this->seoModel->create();
$this->seoModel->saveAll($seoData);
$id = $this->seoModel->id;
}
}
您的SEO模型可能包含此代码:
/**
* AfterSave function, called after an SEO item is saved
* @param bool $created
*/
public function afterSave($created){
parent::afterSave($created);
// Now we need to create our cached routes file
$this->createRouteFile();
// Clear any cached routes
CacheEngine::clearGroup('router');
}
/**
* Cleans up a slug, preserving slash characters
* @param $slug
* @return string
*/
public function sanitizeSlug($slug){
$slugParts = explode('/', $slug);
foreach($slugParts as $slugIndex => $slugPart){
$slugParts[$slugIndex] = $this->createSlugFromString($slugPart);
}
$slug = implode('/', $slugParts);
return $slug;
}
/**
* Creates/Updates the routes file by going through all the routes in the database and writing them to the routes file
*/
public function createRouteFile(){
$databaseRoutes = $this->find(
'all',
array(
'recursive' => -1,
'fields' => array(
'plugin',
'model',
'foreign_key',
'action',
'request_uri'
)
)
);
$fileContents = '';
$fileContents .= "<?php\n";
$fileContents .= "/** Automatically generated by " . __FILE__ . " on " . date('Y-m-d H:i:s') . " */\n";
foreach($databaseRoutes as $routeKey => $routeDetails){
$routeLine = "Router::connect('" . addcslashes ( $routeDetails[$this->alias]['request_uri'], "'" ) . "', array(
'plugin' => '" . addcslashes(Inflector::underscore($routeDetails[$this->alias]['plugin']), "'") . "',
'controller' => '" . addcslashes(Inflector::underscore($routeDetails[$this->alias]['model']), "'") . "',
'action' => '" . addcslashes($routeDetails[$this->alias]['action'], "'") . "',
" . addcslashes($routeDetails[$this->alias]['foreign_key'], "'") . "));\n";
$fileContents .= $routeLine;
}
// Write the routes data to our file. Note that SEO_ROUTES_FILE is defined in /app/Module/Core/Config/Routes.php
$success = file_put_contents(SEO_ROUTES_FILE, $fileContents);
if(!$success){
throw new Exception("SEO Routes file unwritable. Check the permissions of: " . SEO_ROUTES_FILE);
}
}
祝你好运,这是一个难题,这个解决方案对我来说效果很好,并允许编辑任何你想要的SEO网址(即使它违反了你的其他页面的惯例)。当客户雇用一个想要彻底改变某些页面的SEO网址的专业SEO公司时,这很有用。