محسن
3 سال پیش توسط محسن مطرح شد
15 پاسخ

جستجو در داده های encrypted

سلام
دوستان در یک پروژه لاراول ۵.۴ در table داده name به صورت encrypted هست

میخوام جستجو کنم با متد get
باقی داده هارو میتونم جستجو کنم اما داده name چون encrypted هست نمیتونم جستجو کنم

ممنون میشم راهنمایی کنید که چطور باید این کارو انجام بدم؟


ثبت پرسش جدید
مهران مرندی
تخصص : برنامه نویس
@mehranmarandi 3 سال پیش مطرح شد
0

خب اول یه اشکال تو رجکس این کد بود که برعکس کار میکرد
این صحیحه

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 خارج کنید چون بعد از این که تعداد رکورد های این جدول زیادتر بشه سرعت جستجو بسیار کند میشه


محسن
تخصص : تازه کارم :)
@furiousboy.nic 3 سال پیش مطرح شد
0

به این صورت دارم جستجو میکنم


        if ($request->has('name') && !empty($request->get('name'))) {
            $users->where('name', 'like', '%' . $request->get('name') . '%');
        }

تصویر نوع encrypted
توضیح تصویر رو وارد کنید


مهران مرندی
تخصص : برنامه نویس
@mehranmarandi 3 سال پیش مطرح شد
0

اول باید ببینید متد encryption چی بوده، شما میتونید همون رمز نگاری رو روی

$request->get('name')

انجام بدید و بعد کوئری رو اجرا کنید.


محسن
تخصص : تازه کارم :)
@furiousboy.nic 3 سال پیش مطرح شد
0

@mehranmarandi90
از کجا متد رو پیدا کنم؟
آیا میشه به صورت like هم سرچ کرد؟
میشه بیشتر راهنمایی کنید
ممنون


مهران مرندی
تخصص : برنامه نویس
@mehranmarandi 3 سال پیش مطرح شد
0

نوع داده ای که نشون دادید رو سرچ کنید، یا اینکه تو کد بگردید ببینید چطور ایجاد شده
اما در مورد جستجو:مثلا من اگر بخوام mehran رو جستجو کنم قطعا به نتیجه ای نمیرسم، چون اسم mehran به صورت کد شده در دیتابیس ذخیره شده، مثلا تبدیل شده به kd37dbslfxuwjxhd
پس من باید اول mehran رو تبدیل کنم به اون رشته کد شده بعد جستجو کنم


محسن
تخصص : تازه کارم :)
@furiousboy.nic 3 سال پیش آپدیت شد
0

@mehranmarandi90

الان این طوری سرچ میکنه با متد 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'
 ];

مهران مرندی
تخصص : برنامه نویس
@mehranmarandi 3 سال پیش مطرح شد
0

خب بله الان متوجه شدم سوالتون رو
در لاراول اساس این کار اینه گاهی شما نمیخوایید بعضی رکورد ها در دیتابیس قابل مشاهده باشن، پس در مدل تعریف میکنی که یه 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 به نظرم نميرسه


محسن
تخصص : تازه کارم :)
@furiousboy.nic 3 سال پیش مطرح شد
0

@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 همه چیز نمایش داده میشه


مهران مرندی
تخصص : برنامه نویس
@mehranmarandi 3 سال پیش مطرح شد
0

اون json تمام کاربرانی هست که بر اساس جستجو شما پیدا شدن، باید به شکلی که میخوایید نمایششون بدید


محسن
تخصص : تازه کارم :)
@furiousboy.nic 3 سال پیش مطرح شد
0

@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('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.

میشه این کد رو برام اوکی کنی


مهران مرندی
تخصص : برنامه نویس
@mehranmarandi 3 سال پیش مطرح شد
0

خب اول یه اشکال تو رجکس این کد بود که برعکس کار میکرد
این صحیحه

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 خارج کنید چون بعد از این که تعداد رکورد های این جدول زیادتر بشه سرعت جستجو بسیار کند میشه


محسن
تخصص : تازه کارم :)
@furiousboy.nic 3 سال پیش آپدیت شد
1

@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

اینطوری کدهام خوبه و بهینه هست؟


مهران مرندی
تخصص : برنامه نویس
@mehranmarandi 3 سال پیش آپدیت شد
0

اینطوری خطا دریافت نمیکنی
در حالتی که کاربر اسمی رو جستجو میکنه رکورد ها 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 نکنید.


محسن
تخصص : تازه کارم :)
@furiousboy.nic 3 سال پیش مطرح شد
0

@mehranmarandi90
خب چطور از حالت Encrypt خارش کنم

تو کل دیتابیس به این شکل هست
آیا میشه تو دیتابیس دستوری داد که درست بشه؟


مهران مرندی
تخصص : برنامه نویس
@mehranmarandi 3 سال پیش آپدیت شد
0

برای حذف encryption روی attribute هایی که نیاز به جستجو دارن باید تو مدل مربوطه name رو از

protected $encrypts = [
        'name'
 ];

حذف کنی، برای رکورد هایی که در دیتابیس ذخیره شده، چون encryption در سمت کد php انجام شده نمیشه توی خود دیتابیس decrypt کردشون، یه راه سریع میتونه این باشه که یه متد بنویسی که کل رکورد های جدول user رو بگیره، مقدار کدگذاری شده user رو decrypt کنه و در همون ردیف مقدار رو جایگزین مقدار کد گذاری شده بکنه، و بعد هم این کد رو حذف کنید
*قبلش حتما از اون جدول بک آپ تهیه کنید.


محسن
تخصص : تازه کارم :)
@furiousboy.nic 3 سال پیش مطرح شد
1

@mehranmarandi90
تشکر از راهنماییت


برای ارسال پاسخ لازم است وارد شده یا ثبت‌نام کنید

ورود یا ثبت‌نام