Php Silverstripe:清理URL
我目前有一个显示员工档案的模块。它是这样工作的:Php Silverstripe:清理URL,php,content-management-system,silverstripe,Php,Content Management System,Silverstripe,我目前有一个显示员工档案的模块。它是这样工作的: 职员持有者:显示所有职员的列表 员工档案:显示“StaffMember”表中的数据库记录 员工档案使用模板“StaffHolder_Profile.ss”。显然,“profile”是显示员工简介的操作。“显示配置文件”操作在如下URL上运行: 'http://域/staff/profile/记录id' 我被要求从这些URL中删除“profile/id”。据我所知,这是不可能的,因为模块依赖于URL才能工作?(它使用URL变量…) 这是真的吗?
- 职员持有者:显示所有职员的列表
- 员工档案:显示“StaffMember”表中的数据库记录
这是真的吗?是否有一种方法可以从本质上“清理”URL,使新URL为“”您可以通过覆盖页面控制器索引中的路由参数“Action”来实现特定的URL模式。我不建议这样做。相反,我建议您为页面创建一个特定的操作,例如“domain/staff/view/…”。我下面的例子确实覆盖了路由参数“Action”,但只是为了满足您的问题 您可以将标识符基于一个名称,但诸如缺少详细信息和/或名称匹配之类的不一致会产生问题,这些示例中没有涉及到其中的大部分问题。唯一标识符会更好 我还没有测试运行这段代码,很抱歉出现了错误 - 示例1:速度较慢,但所需工作量较少 员工持股人/控制员:
public function index() {
/**
* @internal This will display the first match ONLY. If you'd like to
* account for member's with exactly the same name, generate and store the
* slug against their profile... See Example 2 for that.
*/
// Re-purpose the 'Action' URL param (not advisable)
$slug = $this->getRequest()->param('Action');
// Partial match members by first name
$names = explode('-', $slug);
$matches = Member::get()->filter('FirstName:PartialMatch', $names[0]);
// Match dynamically
$member = null;
foreach($matches as $testMember) {
// Uses preg_replace to remove all non-alpha characters
$testSlug = strtolower(
sprintf(
'%s-%s',
preg_replace("/[^A-Za-z]/", '', $testMember->FirstName),
preg_replace("/[^A-Za-z]/", '', $testMember->Surname)
)
); // Or use Member::genereateSlug() from forthcoming example MemberExtension
// Match member (will stop at first match)
if($testSlug == $slug) {
$member = $testMember;
break;
}
}
// Handle invalid requests
if(!$member) {
return $this->httpError(404, 'Not Found');
}
/**
* @internal If you're lazy and want to use your existing template
*/
return $this->customise(array(
'Profile' => $member
))->renderWith(array('StaffHolder_profile', 'Page'));
}
public function index() {
// Re-purpose the action URL param (not advisable)
$slug = $this->getRequest()->param('Action');
// Check for member
$member = Member::get()->filter('Slug', $slug)->first();
// Handle invalid requests
if(!$member) {
return $this->httpError(404, 'Not Found');
}
/**
* @internal If you're lazy and want to use your existing template
*/
return $this->customise(array(
'StaffMember' => $member
))->renderWith('StaffHolder_profile');
}
-
示例2:
config.yml:
Member:
extensions:
- MemberExtension
MemberExtension.php:
class MemberExtension extends DataExtension {
private static $db = array(
'Slug' => 'Varchar' // Use 'Text' if it's likely that there will be a value longer than 255
);
public function generateSlug() {
// Uses preg_replace to remove all non-alpha characters
return strtolower(
sprintf(
'%s-%s',
preg_replace("/[^A-Za-z]/", '', $this->owner->FirstName),
preg_replace("/[^A-Za-z]/", '', $this->owner->Surname)
)
);
}
public function onBeforeWrite() {
// Define slug
if(!$this->owner->Slug)) {
$slug = $this->generateSlug();
$count = Member::get()->filter('Slug:PartialMatch', $slug)->Count();
// Check for unique
$unique = null;
$fullSlug = $slug;
while(!$unique) {
// Add count e.g firstname-surname-2
if($count > 0) {
$fullSlug = sprintf('%s-%s', $slug, ($count+1));
}
// Check for pre-existing
if(Member::get()->filter('Slug:PartialMatch', $fullSlug)->First()) {
$count++; // (Try again with) increment
} else {
$unique = true;
}
}
// Update member
$this->owner->Slug = $fullSlug;
}
}
}
员工持股人/控制员:
public function index() {
/**
* @internal This will display the first match ONLY. If you'd like to
* account for member's with exactly the same name, generate and store the
* slug against their profile... See Example 2 for that.
*/
// Re-purpose the 'Action' URL param (not advisable)
$slug = $this->getRequest()->param('Action');
// Partial match members by first name
$names = explode('-', $slug);
$matches = Member::get()->filter('FirstName:PartialMatch', $names[0]);
// Match dynamically
$member = null;
foreach($matches as $testMember) {
// Uses preg_replace to remove all non-alpha characters
$testSlug = strtolower(
sprintf(
'%s-%s',
preg_replace("/[^A-Za-z]/", '', $testMember->FirstName),
preg_replace("/[^A-Za-z]/", '', $testMember->Surname)
)
); // Or use Member::genereateSlug() from forthcoming example MemberExtension
// Match member (will stop at first match)
if($testSlug == $slug) {
$member = $testMember;
break;
}
}
// Handle invalid requests
if(!$member) {
return $this->httpError(404, 'Not Found');
}
/**
* @internal If you're lazy and want to use your existing template
*/
return $this->customise(array(
'Profile' => $member
))->renderWith(array('StaffHolder_profile', 'Page'));
}
public function index() {
// Re-purpose the action URL param (not advisable)
$slug = $this->getRequest()->param('Action');
// Check for member
$member = Member::get()->filter('Slug', $slug)->first();
// Handle invalid requests
if(!$member) {
return $this->httpError(404, 'Not Found');
}
/**
* @internal If you're lazy and want to use your existing template
*/
return $this->customise(array(
'StaffMember' => $member
))->renderWith('StaffHolder_profile');
}
嵌套URL是SiteTree类的默认行为。每个子页面URL段都会添加到父完整URL。因此,通过下面的页面层次结构,您可以获得干净的URL
Staff (StaffHolder, /staff)
|- John Doe (StaffProfilePage, /staff/john-doe)
|- Marie Smith (StaffProfilePage, /staff/marie-smith)
您可以在StaffHolder.ss模板中使用
<ul>
<% loop $Children %>
<li><a href="$Link">$Title</a></li>
<% end_loop %>
</ul>
您可以通过自定义路由实现这一点,但可能成员名称不唯一,因此您会遇到同名成员的问题。您是将其作为前端页面还是在CMS中处理?你有用户登录系统吗?(然后可以在会话中找到当前用户,请参阅CMS成员类)是否使用SiteTree::嵌套的URL?(然后StaffProfile可以嵌套在页面中。)是的,您可以在StaffHolder\u Controller::index($request)
中处理干净的url,其中$name=$request->getParam('ID')
@GregSmirnov谢谢你的回复。这是前端。是的,有一个登录系统,但是人员页面将数据对象列表显示为页面。它不是当前用户的配置文件。什么是嵌套url?该控制器功能的具体功能是什么?@Dallby为了避免同名员工之间的名字和姓氏冲突,您也可以将ID附加到URL,例如domain/staff/123 staff-member-name