سلام
دوستان در یک پروژه لاراول ۵.۴ در table داده name به صورت encrypted هست
میخوام جستجو کنم با متد get
باقی داده هارو میتونم جستجو کنم اما داده name چون encrypted هست نمیتونم جستجو کنم
ممنون میشم راهنمایی کنید که چطور باید این کارو انجام بدم؟
خب اول یه اشکال تو رجکس این کد بود که برعکس کار میکرد
این صحیحه
public function search($searchValue){
$users = User::all()->filter(function($user) use($searchValue) {
if(preg_match('/' . $searchValue. '/', $user->name)) {
return $user;
}
});
در این کد ما داریم کل رکورد های جدول user رو میگیرم و فیلتر میکنیم
بعد از این کار نمیشه روی این رکورد ها pagination انجام داد. یه راه اینه که به جای متد all از pagination استفاده کنید مثل کد زیر
public function search($searchValue){
$users = User::paginate(20)->filter(function($user) use($searchValue) {
if(preg_match('/' . $searchValue. '/', $user->name)) {
return $user;
}
});
ولی این کار نتیجه مطلوبی نداره چون فیلتر مورد نظر فقط روی 20 رکورد اون صفحه اعمال میشه
برای این کار باید بر اساس همون متد اول جستجو انجام بشه و مجدد متد پجینیت رو خودتون بنویسید
در مجموع پیشنهاد میکنم اگر روی این رکورد میخوایید جستجو انجام بدید اون رو از حالت Encrypt خارج کنید چون بعد از این که تعداد رکورد های این جدول زیادتر بشه سرعت جستجو بسیار کند میشه
به این صورت دارم جستجو میکنم
if ($request->has('name') && !empty($request->get('name'))) {
$users->where('name', 'like', '%' . $request->get('name') . '%');
}
تصویر نوع encrypted
اول باید ببینید متد encryption چی بوده، شما میتونید همون رمز نگاری رو روی
$request->get('name')
انجام بدید و بعد کوئری رو اجرا کنید.
@mehranmarandi90
از کجا متد رو پیدا کنم؟
آیا میشه به صورت like هم سرچ کرد؟
میشه بیشتر راهنمایی کنید
ممنون
نوع داده ای که نشون دادید رو سرچ کنید، یا اینکه تو کد بگردید ببینید چطور ایجاد شده
اما در مورد جستجو:مثلا من اگر بخوام mehran رو جستجو کنم قطعا به نتیجه ای نمیرسم، چون اسم mehran به صورت کد شده در دیتابیس ذخیره شده، مثلا تبدیل شده به kd37dbslfxuwjxhd
پس من باید اول mehran رو تبدیل کنم به اون رشته کد شده بعد جستجو کنم
الان این طوری سرچ میکنه با متد post
if (!empty($name)) {
foreach ($users as $key => $user) {
if (!preg_match('/' . $name . '/', $user->name))
unset($users[$key]);
}
}
$search = true;
با این روش داره سرچ میکنه بخشی از اسم طرف رو میزنی میاره یعنی به صورت like داره کار میکنه دیگه
من زیاد اطلاعات ندارم درمورد این روش
میشه یه قطعه کد بدید که من با متد get تست کنم
اگر اطلاعاتی از هرکدوم از بخش ها میخوایید بهم بگید که بفرستم تا بتونم اوکی کنم
تو فایل user.php این طوریه
use Delatbabel\Elocrypt\Elocrypt;
use Elocrypt;
protected $encrypts = [
'name'
];
خب بله الان متوجه شدم سوالتون رو
در لاراول اساس این کار اینه گاهی شما نمیخوایید بعضی رکورد ها در دیتابیس قابل مشاهده باشن، پس در مدل تعریف میکنی که یه attribute بصورت کد شده ذخیره میشه، این کد گذاری بصورت AES انجام میشه
ساخت رشته کد شده به شکلی هست که شما اگر ورودی یکسان بهش بدی هر بار ممکنه یک رشته کد شده متفاوت برگردونه، یعنی اگر دوتا کاربرت اسمشون mohsen باشه در دیتابیس دو تا رشته کد شده متفاوت نمایش داده میشه و باید اون ها رو decrypt کنی تا رکورد اصلی رو ببینی
پس برای جستجو در این جدول کار سختی داری، باید کل رکورد ها رو بخونی دونه به دونه decrypt انجام بدی و با مقدار مورد نظرت مقایسه کنی. دقیقا کدی که فرستادی به همین شکل داره عمل میکنه و از Regex استفاده میکنه
public function search($searchValue){
$users = User::all()->filter(function($user) use($searchValue) {
if(!preg_match('/' . $searchValue. '/', $user->name)) {
return $user;
}
});
كد بالا هم درست مثل همون كدي هست كه خودت نوشتي، با توجه به شرايطي كه گفتم راه ديگه اي بجز regex به نظرم نميرسه
@mehranmarandi90
من این کد رو قرار دادم
if ($request->has('name') && !empty($request->get('name'))) {
$searchValue = $request->name;
$users = User::all()->filter(function($user) use($searchValue) {
if(!preg_match('/' . $searchValue. '/', $user->name)) {
return $user;
}
});
return $users;
}
اما وقتی این کد رو قرار میدم داخل صفحه سفیدی به صورت json همه چیز نمایش داده میشه
اون json تمام کاربرانی هست که بر اساس جستجو شما پیدا شدن، باید به شکلی که میخوایید نمایششون بدید
public function getLists(Request $request)
{
$users = User::orderBy('id', "desc");
if ($request->has('id') && $request->id != "") {
$users->where('id', $request->id);
}
if ($request->has('name') && !empty($request->get('name'))) {
$searchValue = $request->name;
$users = User::all()->filter(function($user) use($searchValue) {
if(!preg_match('/' . $searchValue. '/', $user->name)) {
return $user;
}
});
}
if ($request->has('phone') && $request->phone != "") {
$users->where('phone', $request->phone);
}
if ($request->has('melicode') && $request->melicode != "") {
$users->where('melicode', $request->melicode);
}
if ($request->has('email') && !empty($request->get('email'))) {
$users->where('email', 'like', '%' . $request->get('email') . '%');
}
if ($request->has('username') && !empty($request->get('username'))) {
$users->where('username', 'like', '%' . $request->get('username') . '%');
}
if ($request->has('account_number') && !empty($request->get('account_number'))) {
$users->where('account_number', 'like', '%' . $request->get('account_number') . '%');
}
if ($request->has('postalcode') && !empty($request->get('postalcode'))) {
$users->where('postalcode', 'like', '%' . $request->get('postalcode') . '%');
}
if ($request->has('type') && $request->type != "all") {
$users->where('type', $request->type);
}
if ($request->has('confirmed') && $request->confirmed != "all") {
$users->where('confirmed', $request->confirmed);
}
if ($request->has('status') && $request->status != "all") {
$users->where('status', $request->status);
}
if ($request->has('hasGateway') && $request->hasGateway != "all") {
$users->where('hasGateway', $request->hasGateway);
}
if ($request->has('showpage') && !empty($request->get('showpage'))) {
$users = $users->paginate('9999999');
} else {
$users = $users->paginate('20');
}
$hasFilter = count($request->except('page')) ? true : false;
return view("admin.users.lists", compact('users', 'hasFilter'));
}
من الان این کد رو دارم که ارور میگیرم Method paginate does not exist.
میشه این کد رو برام اوکی کنی
خب اول یه اشکال تو رجکس این کد بود که برعکس کار میکرد
این صحیحه
public function search($searchValue){
$users = User::all()->filter(function($user) use($searchValue) {
if(preg_match('/' . $searchValue. '/', $user->name)) {
return $user;
}
});
در این کد ما داریم کل رکورد های جدول user رو میگیرم و فیلتر میکنیم
بعد از این کار نمیشه روی این رکورد ها pagination انجام داد. یه راه اینه که به جای متد all از pagination استفاده کنید مثل کد زیر
public function search($searchValue){
$users = User::paginate(20)->filter(function($user) use($searchValue) {
if(preg_match('/' . $searchValue. '/', $user->name)) {
return $user;
}
});
ولی این کار نتیجه مطلوبی نداره چون فیلتر مورد نظر فقط روی 20 رکورد اون صفحه اعمال میشه
برای این کار باید بر اساس همون متد اول جستجو انجام بشه و مجدد متد پجینیت رو خودتون بنویسید
در مجموع پیشنهاد میکنم اگر روی این رکورد میخوایید جستجو انجام بدید اون رو از حالت Encrypt خارج کنید چون بعد از این که تعداد رکورد های این جدول زیادتر بشه سرعت جستجو بسیار کند میشه
@mehranmarandi90
ممنون ازت مهران جان
من در آخر کدم رو این طوری زدم
public function getLists(Request $request)
{
$users = User::orderBy('id', "desc");
if ($request->has('id') && $request->id != "") {
$users->where('id', $request->id);
}
if ($request->has('name') && !empty($request->get('name'))) {
$searchValue = $request->name;
$users = User::all()->filter(function($user) use($searchValue) {
if(preg_match('/' . $searchValue. '/', $user->name)) {
return $user;
}
});
}
if ($request->has('phone') && $request->phone != "") {
$users->where('phone', $request->phone);
}
if ($request->has('email') && !empty($request->get('email'))) {
$users->where('email', 'like', '%' . $request->get('email') . '%');
}
if ($request->has('username') && !empty($request->get('username'))) {
$users->where('username', 'like', '%' . $request->get('username') . '%');
}
if ($request->has('account_number') && !empty($request->get('account_number'))) {
$users->where('account_number', 'like', '%' . $request->get('account_number') . '%');
}
if ($request->has('type') && $request->type != "all") {
$users->where('type', $request->type);
}
if ($request->has('confirmed') && $request->confirmed != "all") {
$users->where('confirmed', $request->confirmed);
}
if ($request->has('status') && $request->status != "all") {
$users->where('status', $request->status);
}
if ($request->has('hasGateway') && $request->hasGateway != "all") {
$users->where('hasGateway', $request->hasGateway);
}
if ($request->has('showpage') && !empty($request->get('showpage'))) {
$users = $users->paginate('9999999');
}
elseif ($request->has('name') && !empty($request->get('name'))) {
$users = $users;
}
else{
$users = $users->paginate('20');
}
//$users = $users->paginate('20');
$hasFilter = count($request->except('page')) ? true : false;
return view("admin.users.lists", compact('users', 'hasFilter'));
}
به نظرت خوبه؟
تو list.blade هم این طوری کردم
@if(request('name')== true)
@else
@if ($users->isEmpty())
<center><br>هیچ کاربری پیدا نشد<br></center>
@endif
@if($hasFilter)
<div style="float:left;margin-left:10px"> {!! $users->appends(request()->all())->render() !!}</div>
@else
<div style="float:left;margin-left:10px"> {!! $users->render() !!}</div>
@endif
@endif
اینطوری کدهام خوبه و بهینه هست؟
اینطوری خطا دریافت نمیکنی
در حالتی که کاربر اسمی رو جستجو میکنه رکورد ها paginate شده نمایش داده نمیشن و اگر نتایج زیاد باشن یه لیست طولانی در صفحه مشاهده میشه
خروجی users رو در حالتی که نتیجه جستجو رو برمیگردونه میتونی با چیزی شبیه کد زیر خودت paginate کنی
use Illuminate\Pagination\Paginator;
public function paginate($items, $perPage = 5, $page = null, $options = [])
{
$page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
$items = $items instanceof Collection ? $items : Collection::make($items);
return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
}
ولی در مورد بهینه بودن خیر اصلا بهینه نیست تصور کن در دیتابیس 1000 کاربر داشته باشی که عدد بسیار کوچکیه وقتی روی همین تعداد کدت اجرا بشه، کل این 1000 رکورد خونده میشه، و یه loop روی این 1000 رکورد اجرا میشه و 1000 بار عملیات decrypt انجام میشه، به همین دلیل همیشه توصیه میشه اگر میخوایید روی رکوردی جستجو انجام بدید اون رو encrypt نکنید.
@mehranmarandi90
خب چطور از حالت Encrypt خارش کنم
تو کل دیتابیس به این شکل هست
آیا میشه تو دیتابیس دستوری داد که درست بشه؟
برای حذف encryption روی attribute هایی که نیاز به جستجو دارن باید تو مدل مربوطه name رو از
protected $encrypts = [
'name'
];
حذف کنی، برای رکورد هایی که در دیتابیس ذخیره شده، چون encryption در سمت کد php انجام شده نمیشه توی خود دیتابیس decrypt کردشون، یه راه سریع میتونه این باشه که یه متد بنویسی که کل رکورد های جدول user رو بگیره، مقدار کدگذاری شده user رو decrypt کنه و در همون ردیف مقدار رو جایگزین مقدار کد گذاری شده بکنه، و بعد هم این کد رو حذف کنید
*قبلش حتما از اون جدول بک آپ تهیه کنید.
آیا مایل به ارسال نوتیفیکیشن و اخبار از طرف راکت هستید ؟