这是一个棘手的问题。
我的做法是在 /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 路由文件都会更新。
默认情况下,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 url 编辑为你想要的任何内容(即使它违反了其他页面的约定)。当客户聘请专业的 SEO 公司想要完全更改某些页面的 SEO 网址时,这很有用。