问题描述
这段代码显示了来自 October Rainlab Blog 插件的模型 post.PHP 的一小部分。 AfterSave() 函数被修改,当后台有新的 blogPost 被管理员保存时,它会发送一封电子邮件,但是,我想在它实际发布时发送它,并确保它不会多次发送。我怎么能做到这一点?
public function filterFields($fields,$context = null)
{
if (!isset($fields->published,$fields->published_at)) {
return;
}
$user = BackendAuth::getUser();
if (!$user->hasAnyAccess(['rainlab.blog.access_publish'])) {
$fields->published->hidden = true;
$fields->published_at->hidden = true;
}
else {
$fields->published->hidden = false;
$fields->published_at->hidden = false;
}
}
public function afterValidate()
{
if ($this->published && !$this->published_at) {
throw new ValidationException([
'published_at' => Lang::get('rainlab.blog::lang.post.published_validation')
]);
}
}
public function beforeSave()
{
if (empty($this->user)) {
$user = BackendAuth::getUser();
if (!is_null($user)) {
$this->user = $user->id;
}
}
$this->content_html = self::formatHtml($this->content);
}
public function afterSave()
{
$user = BackendAuth::getUser();
if ($user && $user->hasAnyAccess(['rainlab.blog.access_publish'])) {
$susers = Db::select('select * from users where is_activated = ?',[1]);
foreach ($susers as $suser) {
$currentPath = $_SERVER['PHP_SELF'];
$pathInfo = pathinfo($currentPath);
$hostName = $_SERVER['HTTP_HOST'];
$protocol = strtolower(substr($_SERVER["SERVER_PROTOCOL"],5))=='https'?'https':'http';
$protocol.'://'.$hostName.$pathInfo['dirname']."/";
$spost_url = $protocol.'://'.$hostName.$pathInfo['dirname']."/"."nieuws/".$this->attributes['slug'] ;
$stitle = $this->attributes['title'] ;
$body = '<div> Hallo '.$suser->name.'</br> Er is zojuist een nieuws bericht gepubliceerd voor alle leden van mycompany.nl,je kunt hier het bericht lezen aangaande: <a href="'.$spost_url.'">'.$stitle.'</a> </div>' ;
//$from = $user->email ;
$from = 'noreply@mycompany.nl';
$headers = "From: $from\r\n";
$headers .= "Content-type: text/html\r\n";
mail($suser->email,'Nieuws van mycompany',$body,$headers);
}
}
}
/**
* Sets the "url" attribute with a URL to this object.
* @param string $pageName
* @param Controller $controller
* @param array $params Override request URL parameters
*
* @return string
*/
public function setUrl($pageName,$controller,$params = [])
{
$params = array_merge([
'id' => $this->id,'slug' => $this->slug,],$params);
if (empty($params['category'])) {
$params['category'] = $this->categories->count() ? $this->categories->first()->slug : null;
}
// Expose published year,month and day as URL parameters.
if ($this->published) {
$params['year'] = $this->published_at->format('Y');
$params['month'] = $this->published_at->format('m');
$params['day'] = $this->published_at->format('d');
}
return $this->url = $controller->pageUrl($pageName,$params);
}
/**
* Used to test if a certain user has permission to edit post,* returns TRUE if the user is the owner or has other posts access.
* @param User $user
* @return bool
*/
public function canEdit(User $user)
{
return ($this->user_id == $user->id) || $user->hasAnyAccess(['rainlab.blog.access_other_posts']);
}
public static function formatHtml($input,$preview = false)
{
$result = Markdown::parse(trim($input));
// Check to see if the HTML should be cleaned from potential XSS
$user = BackendAuth::getUser();
if (!$user || !$user->hasAccess('backend.allow_unsafe_markdown')) {
$result = Html::clean($result);
}
if ($preview) {
$result = str_replace('<pre>','<pre class="prettyprint">',$result);
}
$result = TagProcessor::instance()->processtags($result,$preview);
return $result;
}
//
// Scopes
//
public function scopeIsPublished($query)
{
return $query
->whereNotNull('published')
->where('published',true)
->whereNotNull('published_at')
->where('published_at','<',Carbon::Now())
;
}
/**
* Lists posts for the frontend
*
* @param $query
* @param array $options display options
* @return Post
*/
public function scopeListFrontEnd($query,$options)
{
/*
* Default options
*/
extract(array_merge([
'page' => 1,'perPage' => 30,'sort' => 'created_at','categories' => null,'exceptCategories' => null,'category' => null,'search' => '','published' => true,'exceptPost' => null
],$options));
$searchableFields = ['title','slug','excerpt','content'];
if ($published) {
$query->isPublished();
}
解决方法
实现此目的的一种方法是扩展 Post 模型。
例如,您创建一个带有 is_notified 字段的新插件和模型。
然后,您将在新插件的 boot() 方法中添加如下内容:
PostModel::extend(function ($model) {
$model->hasOne['your_model'] = ['Author\PluginName\Models\YourModel'];
});
PostsController::extendFormFields(function ($form,$model,$context) {
// Checking for Post instance
if (!$model instanceof PostModel) {
return;
}
// without this code you can get an error saying "Call to a member function hasRelation() on null"
if (!$model->your_model) {
$model->your_model = new YourModel;
}
}
然后您可以在 afterSave 方法中使用该新模型
public function afterSave()
{
$user = BackendAuth::getUser();
if ($user && $user->hasAnyAccess(['rainlab.blog.access_publish'])) {
$susers = Db::select('select * from users where is_activated = ?',[1]);
foreach ($susers as $suser) {
...
if ($this->your_model->is_notified != true) {
mail($suser->email,'Nieuws van mycompany',$body,$headers);
$this->your_model->is_notified = true;
}
}
}
}
您还应该考虑使用扩展方法而不是修改 3rd 方插件代码。这将允许您更新插件而不会丢失您的编辑。像这样:
PostModel::extend(function ($model) {
$model->hasOne['your_model'] = ['Author\PluginName\Models\YourModel'];
// You can transfer your afterSave code here!
$model->bindEvent('model.afterSave',function () use ($model) {
$user = BackendAuth::getUser();
if ($user && $user->hasAnyAccess(['rainlab.blog.access_publish'])) {
..
}
});
});
如果您有任何问题,请告诉我!