|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Created by PhpStorm.
|
|
|
|
* User: zhl
|
|
|
|
* Date: 2024/09/30
|
|
|
|
* Time: 11:51
|
|
|
|
*/
|
|
|
|
namespace App\Console\Commands\Inquiry;
|
|
|
|
|
|
|
|
use App\Helper\Translate;
|
|
|
|
use App\Models\Inquiry\ReInquiryDetail;
|
|
|
|
use App\Models\Inquiry\ReInquiryDetailLog;
|
|
|
|
use App\Models\Inquiry\ReInquiryForm;
|
|
|
|
use App\Models\Inquiry\ReInquiryTask;
|
|
|
|
use App\Models\Inquiry\ReInquiryText;
|
|
|
|
use App\Models\Project\Project;
|
|
|
|
use App\Models\WebSetting\WebLanguage;
|
|
|
|
use Illuminate\Console\Command;
|
|
|
|
use Illuminate\Support\Arr;
|
|
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
use Illuminate\Support\Str;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Class RelayInquiry
|
|
|
|
* @package App\Console\Commands\Inquiry
|
|
|
|
*/
|
|
|
|
class RelayInquiry extends Command
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* The name and signature of the console command.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
protected $signature = 'relay_inquiry';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The console command description.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
protected $description = '转发询盘:拆分转发数据';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new command instance.
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function __construct()
|
|
|
|
{
|
|
|
|
parent::__construct();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 模拟访问来源占比
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $lyzb = [
|
|
|
|
'https://www.google.com/' => 630,
|
|
|
|
'http://www.google.com/' => 30,
|
|
|
|
'http://www.bing.com/' => 20,
|
|
|
|
'https://www.bing.com/' => 5,
|
|
|
|
'https://www.youtube.com/' => 5,
|
|
|
|
'https://search.yahoo.com/' => 5,
|
|
|
|
'https://www.facebook.com/' => 5,
|
|
|
|
];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 俄语站 模拟访问来源占比
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $eylyzb = [
|
|
|
|
'https://www.yandex.com/' => 630,
|
|
|
|
'https://www.google.com/' => 30,
|
|
|
|
'http://www.google.com/' => 30,
|
|
|
|
'http://www.bing.com/' => 20,
|
|
|
|
'https://www.bing.com/' => 5,
|
|
|
|
'https://www.youtube.com/' => 5,
|
|
|
|
'https://search.yahoo.com/' => 5,
|
|
|
|
'https://www.facebook.com/' => 5,
|
|
|
|
];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* PC端访问头信息
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $pc_ua = [
|
|
|
|
0 => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
|
|
|
|
1 => 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36',
|
|
|
|
2 => 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1'
|
|
|
|
];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 移动端访问头信息
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $mobile_ua = [
|
|
|
|
0 => 'Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko; googleweblight) Chrome/38.0.1025.166 Mobile Safari/535.19',
|
|
|
|
];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* google域名后缀
|
|
|
|
* @var string[]
|
|
|
|
*/
|
|
|
|
protected $suffix = [
|
|
|
|
'co.jp' => '日本',
|
|
|
|
'com.tr' => '土耳其',
|
|
|
|
'nl' => '荷兰',
|
|
|
|
'ru' => '俄罗斯',
|
|
|
|
'fr' => '法国',
|
|
|
|
'co.kr' => '韩国',
|
|
|
|
'fi' => '芬兰',
|
|
|
|
'be' => '比利时',
|
|
|
|
'lt' => '立陶宛',
|
|
|
|
'es' => '西班牙',
|
|
|
|
'it' => '意大利',
|
|
|
|
'com.au' => '澳大利亚',
|
|
|
|
'no' => '挪威',
|
|
|
|
'al' => '阿尔巴尼亚',
|
|
|
|
'pt' => '葡萄牙',
|
|
|
|
'lv' => '拉脱维亚',
|
|
|
|
'hu' => '匈牙利',
|
|
|
|
'cz' => '捷克',
|
|
|
|
'de' => '德国',
|
|
|
|
'ca' => '加拿大',
|
|
|
|
'co.in' => '印度',
|
|
|
|
'co.uk' => '英国',
|
|
|
|
'com.vn' => '越南',
|
|
|
|
'com.br' => '巴西',
|
|
|
|
'co.il' => '以色列',
|
|
|
|
'pl' => '波兰',
|
|
|
|
'com.eg' => '埃及',
|
|
|
|
'co.th' => '泰国',
|
|
|
|
'sk' => '斯洛伐克',
|
|
|
|
'ro' => '罗马尼亚',
|
|
|
|
'com.mx' => '墨西哥',
|
|
|
|
'com.my' => '马来西亚',
|
|
|
|
'com.pk' => '巴基斯坦',
|
|
|
|
'co.nz' => '新西兰',
|
|
|
|
'co.za' => '南非',
|
|
|
|
'com.ar' => '阿根廷',
|
|
|
|
'com.kw' => '科威特',
|
|
|
|
'com.sg' => '新加坡',
|
|
|
|
'com.co' => '哥伦比亚',
|
|
|
|
'co.id' => '印度尼西亚',
|
|
|
|
'gr' => '希腊',
|
|
|
|
'bg' => '保加利亚',
|
|
|
|
'mn' => '蒙古',
|
|
|
|
'dk' => '丹麦',
|
|
|
|
'com.sa' => '沙特阿拉伯',
|
|
|
|
'com.pe' => '秘鲁',
|
|
|
|
'com.ph' => '菲律宾',
|
|
|
|
'com.ua' => '乌克兰',
|
|
|
|
'ge' => '格鲁吉亚',
|
|
|
|
'ae' => '阿拉伯联合酋长国',
|
|
|
|
'tn' => '突尼斯',
|
|
|
|
];
|
|
|
|
|
|
|
|
protected $otherzb = [700, 300]; //模拟访问来源占比 (非美国) google.com|google.其他后缀
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function handle()
|
|
|
|
{
|
|
|
|
while (true) {
|
|
|
|
$inquiry = $this->getInquiry();
|
|
|
|
if ($inquiry->isEmpty()){
|
|
|
|
$this->logChannel()->info('未发现待处理询盘!');
|
|
|
|
$this->output('未发现待处理询盘!');
|
|
|
|
sleep(60);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->output('开始处理本轮询盘!');
|
|
|
|
foreach ($inquiry as $key=>$val) {
|
|
|
|
$this->output('询盘ID:' . $val->id);
|
|
|
|
// 询盘对应广告
|
|
|
|
$ad_task = $this->getAdTask($val->ad_id);
|
|
|
|
// 没有获取到转发任务
|
|
|
|
if (empty($ad_task)) {
|
|
|
|
$val->status = ReInquiryForm::STATUS_FORGO;
|
|
|
|
$val->remark = '未找到需要转发的广告任务!';
|
|
|
|
$val->save();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// 未设置对法对象
|
|
|
|
if (empty($ad_task['target'])) {
|
|
|
|
$val->status = ReInquiryForm::STATUS_FORGO;
|
|
|
|
$val->remark = '广告任务转发对象为空!';
|
|
|
|
$val->save();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$this->relayDetail($ad_task, $val);
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
$this->logChannel()->info('执行询盘错误:' . $e->getMessage());
|
|
|
|
$this->output('执行询盘错误:' . $e->getMessage());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$this->output('本轮询盘处理结束!');
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 创建转发详情
|
|
|
|
* TODO 通过任务生成转发对象, 更具转发对象获取对应数据, 写入着陆记录
|
|
|
|
* @param $task
|
|
|
|
* @param $form
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function relayDetail($task, $form)
|
|
|
|
{
|
|
|
|
$this->output('获取转发对象');
|
|
|
|
// 获取转发对象 重置num数量, array_rand数量不足会报错
|
|
|
|
$task['num'] = $task['num'] > count($task['target']) ? count($task['target']) : $task['num'];
|
|
|
|
$relay_target_key = array_rand($task['target'], $task['num']);
|
|
|
|
if (empty($relay_target_key)) {
|
|
|
|
$this->logChannel()->info('当前任务未发现转发对象!', ['广告任务ID:' . $task['id'], '询盘ID:' . $form->id]);
|
|
|
|
$form->status = ReInquiryForm::STATUS_FORGO;
|
|
|
|
$form->remark = '当前任务未发现转发对象,广告ID: ' . $form->ad_id . '!';
|
|
|
|
$form->save();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($relay_target_key as $key) {
|
|
|
|
// 推送站点
|
|
|
|
$domain = $task['target'][$key]['url'];
|
|
|
|
$is_v6 = $task['target'][$key]['is_v6'];
|
|
|
|
$re_website = 'https://' . $domain . '/';
|
|
|
|
|
|
|
|
$this->output('转发对象:' . $domain);
|
|
|
|
$this->output('获取转发链接');
|
|
|
|
// v6:有邮箱推送主站,没有邮箱推送AMP站;v5:仅推送有邮箱到主站
|
|
|
|
$lang = '';
|
|
|
|
if ($is_v6) {
|
|
|
|
// 获取语种, 6.0是可以确定语种的
|
|
|
|
$project = Project::getProjectByDomain($domain);
|
|
|
|
if (empty($project)) {
|
|
|
|
$this->logChannel()->info('广告任务ID:' . $task['id'] . ', 转发对象:' . $re_website . '非v6链接,转发失败;', ['广告任务ID:' . $task['id'], '询盘ID:' . $form->id]);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$lang = WebLanguage::getLangById($project->main_lang_id ?? 1)['short'];
|
|
|
|
|
|
|
|
// 获取访问明细和着陆页
|
|
|
|
$product_url = $this->getLinksFromSitemap($re_website . 'product_sitemap.xml');
|
|
|
|
$product_cate_url = $this->getLinksFromSitemap($re_website . 'product_category_sitemap.xml');
|
|
|
|
$keywords_url = $this->getLinksFromSitemap($re_website . 'product_keywords_sitemap.xml');
|
|
|
|
$page_url = $this->getLinksFromSitemap($re_website . 'page_sitemap.xml');
|
|
|
|
} else {
|
|
|
|
if($form->email){
|
|
|
|
//通过sitemap拿访问页面
|
|
|
|
$product_url = $this->getLinksFromSitemap($re_website . 'sitemap_post.xml');
|
|
|
|
$product_cate_url = $this->getLinksFromSitemap($re_website . 'sitemap_category.xml');
|
|
|
|
$keywords_url = $this->getLinksFromSitemap($re_website . 'sitemap_post_tag.xml');
|
|
|
|
$page_url = $this->getLinksFromSitemap($re_website . 'sitemap_page.xml');
|
|
|
|
}else{
|
|
|
|
//m站先就往contact-us着陆
|
|
|
|
$product_url = $product_cate_url = $keywords_url = [];
|
|
|
|
$page_url = [$re_website . 'contact-us/'];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 所有可用url
|
|
|
|
$urls = $inquiry_urls = [];
|
|
|
|
$urls[] = $inquiry_urls[] = $re_website;
|
|
|
|
$all_urls = array_merge($urls, $product_url, $product_cate_url, $keywords_url, $page_url);
|
|
|
|
$inquiry_urls = array_merge($urls, $product_cate_url, $keywords_url, $page_url);
|
|
|
|
|
|
|
|
// 随机访问1-3个页面
|
|
|
|
$visit_urls = Arr::random($all_urls, rand(1, count($all_urls) > 3 ? 3 : count($all_urls)));
|
|
|
|
$urls = array_merge($urls, $visit_urls);
|
|
|
|
// 推送着落页只能是 首页、产品分类、单页面、聚合页
|
|
|
|
if(!in_array(end($urls), $inquiry_urls)){
|
|
|
|
$urls[] = Arr::random($inquiry_urls);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->output('获取转发ip');
|
|
|
|
// TODO 获取IP:如果是简码,查询数据库获取对应的国家, 如果是国家使用翻译, 再转化成IP
|
|
|
|
if (strlen($form->country) == 2) {
|
|
|
|
$country = $this->getCountry($form->country);
|
|
|
|
} else {
|
|
|
|
$country = Translate::tran($form->country, 'zh');
|
|
|
|
}
|
|
|
|
// 有国家 通过国家查询, 如果没有获取到就随机获取
|
|
|
|
$where = [];
|
|
|
|
$country && $where['ip_area'] = $country;
|
|
|
|
$ip_data = DB::table('gl_xunpan_ipdata')->where($where)->inRandomOrder()->first();
|
|
|
|
if (empty($ip_data)) {
|
|
|
|
$ip_data = DB::table('gl_xunpan_ipdata')->inRandomOrder()->first();
|
|
|
|
}
|
|
|
|
$ip = $ip_data->ip;
|
|
|
|
$country_name = $ip_data->ip_area;
|
|
|
|
|
|
|
|
$this->output('转发内容');
|
|
|
|
// 推送消息 消息内容小于10个字符, 使用内置询盘内容
|
|
|
|
$message = $form->message;
|
|
|
|
$message_id = 0;
|
|
|
|
if (strlen($message) < 10) {
|
|
|
|
$use_ids = ReInquiryDetail::where(['re_website' => $domain])->where('status', '<>', ReInquiryDetail::STATUS_FAIL)->pluck('text_id')->toArray();
|
|
|
|
$text = ReInquiryText::whereNotIn('id', $use_ids)->where('status', ReInquiryText::STATUS_USABLE)->inRandomOrder()->first();
|
|
|
|
$message = $text->content;
|
|
|
|
$message_id = $text->id;
|
|
|
|
// 获取后,使用次数+1
|
|
|
|
$text->use_time += 1;
|
|
|
|
$text->save();
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->output('获取转发设备信息');
|
|
|
|
// 客户端 头信息 来源
|
|
|
|
$device_port = $form->email ? '1' : '2'; //1 pc 2移动端
|
|
|
|
$user_agent = $form->email ? Arr::random($this->pc_ua) : Arr::random($this->mobile_ua);
|
|
|
|
$referrer = $this->getReferer($country_name, $lang);
|
|
|
|
$this->output('写入数据');
|
|
|
|
|
|
|
|
$pre = 0;
|
|
|
|
$start_time = time();
|
|
|
|
$seconds = rand(300, 900); // 开始时间 从5-15分钟后开始
|
|
|
|
// 写入推送详情
|
|
|
|
$re_detail = ReInquiryDetail::createInquiry($task['id'], $form->id, $domain, $country_name, $ip, $form->full_name, $form->email, $form->phone, $message, $message_id, $device_port,
|
|
|
|
$user_agent, $referrer, $urls, $is_v6, date('Y-m-d H:i:s', $start_time + $seconds));
|
|
|
|
foreach ($urls as $k=>$v){
|
|
|
|
$pre++;
|
|
|
|
$seconds += rand(3,10);
|
|
|
|
ReInquiryDetailLog::createInquiryLog($re_detail->id, ReInquiryDetailLog::TYPE_VISIT, $pre, $v, date('Y-m-d H:i:s', $start_time + $seconds));
|
|
|
|
// 最后一次访问询盘 加上询盘
|
|
|
|
if($k+1 >= count($urls)){
|
|
|
|
$seconds += rand(10,30);
|
|
|
|
$pre++;
|
|
|
|
ReInquiryDetailLog::createInquiryLog($re_detail->id, ReInquiryDetailLog::TYPE_INQUIRY, $pre, $v, date('Y-m-d H:i:s', $start_time + $seconds));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$form->status = ReInquiryForm::STATUS_SUCCESS;
|
|
|
|
$form->save();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 获取待处理询盘表单
|
|
|
|
* @param int $num
|
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
public function getInquiry($num = 10)
|
|
|
|
{
|
|
|
|
$result = ReInquiryForm::where(['status' => ReInquiryForm::STATUS_INIT])->orderBy('id', 'asc')->limit($num)->get();
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 获取广告任务配置数据
|
|
|
|
* @param $ad_id
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function getAdTask($ad_id)
|
|
|
|
{
|
|
|
|
$cache_key = 'inquiry_ads_task';
|
|
|
|
$ads = Cache::get($cache_key, function () use ($cache_key) {
|
|
|
|
$ads = ReInquiryTask::where(['status' => ReInquiryTask::STATUS_OPEN])->get(['id', 'ad_id', 'num', 'target']);
|
|
|
|
$array = [];
|
|
|
|
foreach ($ads as $key=>$val) {
|
|
|
|
$array[$val->ad_id] = $val;
|
|
|
|
}
|
|
|
|
if ($array)
|
|
|
|
Cache::put($cache_key, $array, 60);
|
|
|
|
return $array;
|
|
|
|
});
|
|
|
|
return empty($ads[$ad_id]) ? [] : $ads[$ad_id];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 通过国家简码获取国家名称
|
|
|
|
* @param $code
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function getCountry($code)
|
|
|
|
{
|
|
|
|
$cache_key = 'inquiry_world_country';
|
|
|
|
$country_code = Cache::get($cache_key, function () use ($cache_key) {
|
|
|
|
$country_code = DB::table('gl_world_country_city')->where(['pid' => 0])->pluck('chinese_name', 'iso2')->toArray();
|
|
|
|
Cache::put($cache_key, $country_code, 86400);
|
|
|
|
return $country_code;
|
|
|
|
});
|
|
|
|
return empty($country_code[$code]) ? '' : $country_code[$code];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 获取头信息
|
|
|
|
* @param $ip_area
|
|
|
|
* @param $lang
|
|
|
|
* @return int|string
|
|
|
|
*/
|
|
|
|
public function getReferer($ip_area, $lang)
|
|
|
|
{
|
|
|
|
if($lang == 'ru'){
|
|
|
|
return $this->get_rand($this->eylyzb);
|
|
|
|
}
|
|
|
|
if($ip_area == '美国'){
|
|
|
|
$referer = $this->get_rand($this->lyzb);
|
|
|
|
}else{
|
|
|
|
$referer = 'https://www.google.com/';
|
|
|
|
$suffix = array_search($ip_area, $this->suffix);
|
|
|
|
if($suffix){
|
|
|
|
$res_qtzb = $this->get_rand($this->otherzb);
|
|
|
|
if($res_qtzb == 1){
|
|
|
|
$referer = 'https://www.google.'.$suffix.'/';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $referer;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 概率算法
|
|
|
|
* @param $proArr
|
|
|
|
* @return int|string
|
|
|
|
*/
|
|
|
|
protected function get_rand($proArr)
|
|
|
|
{
|
|
|
|
$result = '';
|
|
|
|
$proSum = array_sum($proArr);
|
|
|
|
foreach ($proArr as $key => $proCur) {
|
|
|
|
$randNum = mt_rand(1, $proSum);
|
|
|
|
if ($randNum <= $proCur) {
|
|
|
|
$result = $key;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
$proSum -= $proCur;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
unset ($proArr);
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 获取sitemap内容
|
|
|
|
* @param $sitemapUrl
|
|
|
|
* @return array|mixed
|
|
|
|
*/
|
|
|
|
function getLinksFromSitemap($sitemapUrl) {
|
|
|
|
try {
|
|
|
|
//忽略cert证书 先下载到临时文件
|
|
|
|
$result = Http::withoutVerifying()->get($sitemapUrl)->body();
|
|
|
|
$tempFilePath = tempnam(sys_get_temp_dir(), 'remote_file_');
|
|
|
|
file_put_contents($tempFilePath, $result);
|
|
|
|
$xml = simplexml_load_file($tempFilePath);
|
|
|
|
$links = [];
|
|
|
|
foreach ($xml->url as $url) {
|
|
|
|
$loc = (string) $url->loc;
|
|
|
|
if(!Str::contains($loc, ['404', 'thanks'])){
|
|
|
|
$links[] = $loc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//随机取20个
|
|
|
|
$total = count($links);
|
|
|
|
return Arr::random($links, $total > 20 ? 20 : $total);
|
|
|
|
}catch (\Exception $e){
|
|
|
|
echo date('Y-m-d H:i:s') . 'sitemap获取失败:' . $e->getMessage() . PHP_EOL;
|
|
|
|
return $links??[];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return \Psr\Log\LoggerInterface
|
|
|
|
*/
|
|
|
|
public function logChannel()
|
|
|
|
{
|
|
|
|
return Log::channel('inquiry_relay');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function output($message)
|
|
|
|
{
|
|
|
|
echo date('Y-m-d H:i:s') . ' | ' . $message . PHP_EOL;
|
|
|
|
}
|
|
|
|
} |
...
|
...
|
|