Searching value in already cache data from database in laravel - laravel

I am learning to make caching and as I know
if(cache::has('cacheKey')) {
cache::get('cacheKey')
} else {
$data=cache::remember('cacheKey',time,function() {
return db::table('user')->get();});
return $data;
}
now question is when I am trying to search a specific data on key and then on result paginate that data for this I did use Cache::remember but how can make this fast when I am using all the time cache::remember function when I am trying to search in cache key, here is code
$page = $req->has('page') ? $req->query('page') : 1;
$keyword = $req->keyword;
if(cache::has('FileData')) {
if(!empty($keyword)) {
$file = cache::remember('FileData'.'search='.$keyword.'page='.$page,1440,function() use ($keyword) {
return File::with('callcase','lettercase','update_table','fileimages')
->where('id','Like','%'.$keyword.'%')
->orWhere('file_name','Like','%'.$keyword.'%')
->orWhere('recieved_by','Like','%'.$keyword.'%')
->orWhere('processed_by','Like','%'.$keyword.'%')
->orWhere('address','Like','%'.$keyword.'%')
->orWhere('contact_no','Like','%'.$keyword.'%')
->orWhere('show_status','Like','%'.$keyword.'%')
->orWhere('Reopen','Like','%'.$keyword.'%')
->orderBy('id','desc')
->paginate(25)
->setpath('');
});
$file->appends(['keyword'=>$keyword]);
if(count($file)>0) {
return view('home')->with('files',$file) ;
} else {
$error = "File does not found , Search another using keyword ";
return view('home')->with('filemsg',$error);
}
} else {
$file = cache::remember('FileData'.'page='.$page,1440,function () {
return File::with('callcase','lettercase','update_table','fileimages')
->orderBy('id','desc')
->paginate(25);});
return view('home')->with('files',$file) ;
}
} else {
$file = cache::remember('FileData',1440,function(){
return File::with('callcase','lettercase','update_table','fileimages')
->orderBy('id','desc')
->paginate(25);
});
return view('home')->with('files',$file);
}
My code is working fine and returning data as i wanted but i am confused on this when every time i am making remember data then how can i make that faster it would faster when i will retrieve data from already cache key and search in them and paginate them , How can i do this and help me if somehow i am doing wrong.

Related

Filter a value in all properties with Laravel

This question is very similar to Laravel filter a value in all columns. Sorry, if it turns out as a duplicate later on, but I have another working code to provide.
What does work is filtering on the client side via JavaScript:
filterfunction : function(entry, filter)
{
if(filter != null)
filter.trim().split(' ').forEach(function(item){
if(!this.eachRecursive(entry, item))
return false;
});
return true;
},
eachRecursive: function(obj, localfilter) {
for(const key in obj) {
if (!obj.hasOwnProperty(key))
continue;
if(typeof obj[key] == "object" && obj[key] !== null){
if(this.eachRecursive(obj[key], localfilter))
return true;
}
else
if((obj[key] + "").toLowerCase().indexOf(localfilter.toLowerCase()) != -1)
return true;
}
return false;
},
The filter function is used as the filter function for the Bootstrap-Vue table component like described in custom-filter-function.
The question is now: how to achieve similar functionality in the Laravel-Backend (for using with Livewire)?
I can imagine, that listing all columns via getColumnListing, mentioned in Laravel filter a value in all columns is possible, but this wouldn't suffice, I still need the relations, like in laravel mysql query with multiple where orwhere and inner join.
Currently, I'm trying out to convert the Eloquent object to JSON and then to parse it, as it includes all the loaded relations eloquent-serialization. But this seems like the last resort and a kind of misuse of serialization.
For now I'm going to use the route over converting to json. However, I found a way to not to parse json by regular expressions. Instead, I convert the jsonified collection back to php objects. With them I'm able to reimplement the functions from above:
private function eachRecursive(stdClass $obj, string $localfilter) {
foreach($obj as $key => $val){
if(is_object($val)){
if($this->eachRecursive($val, $localfilter))
return true;
} elseif(is_array($val)){
foreach($val as $k => $v)
if($this->eachRecursive($v, $localfilter))
return true;
} elseif(stripos(strval($val), $localfilter) !== false){
return true;
}
}
return false;
}
private function filterfunction(Collection $collection, string $filter){
$retVal = [];
foreach (json_decode($collection->toJson()) as $entity){
foreach(explode(' ', trim($filter)) as $localfilter)
if(!$this->eachRecursive($entity, $localfilter))
continue 2;
array_push($retVal, $entity->id);
}
return $retVal;
}

implement update in save

$ahorroga = Ahorroga::findOrFail($id);
$ahorroga->junta_id = $request->junta_id;
$ahorroga->socio_id = $request->socio_id;
$ahorroga->ahorro = $request->ahorro;
$ahorroga->estado = $request->estado;
if ($ahorroga->isDirty()) {
$ahorroga->save();
toast('Ahorro Garantia Editado', 'success');
return redirect('ahorroga');
}
toast('No se detectaron cambios', 'error');
return redirect('ahorroga');
I know I can use and save lines of code, But how to apply the isDirty
Ahorroga::findOrFail($id)->update($request->all());
If I get it correct, then if you want to detect whether you updated stuff updated the table or not then below is the solution.
The best solution for this is to use update(), it returns true or false and based on this you can do your further logic. For ex:
$ahorroga = Ahorroga::find($id);
$ahorroga->junta_id = $request->junta_id;
$ahorroga->socio_id = $request->socio_id;
$ahorroga->ahorro = $request->ahorro;
$ahorroga->estado = $request->estado;
$id_updated = $ahorroga->update();
if($id_updated ) {
//if ture
}else{
//false
}
public function update($id)
{
$ahorroga->fill($request->only([
'junta_id', 'socio_id', 'ahorro','estado',
]);
if(!$ahorroga->isDirty()) {
toast('No se detectaron cambios', 'error');
return back();
}
$ahorroga->save();
toast('Ahorro Garantia Editado', 'success');
return redirect()->route();
}
In place of using isDirty(), you can also use isClean()
if($ahorroga->isClean()) {
// some error handling here
}
isDirty means there was changes. isClean means there was no change.

Laravel help for optimize command script

I'm working with Lumen framework v5.8 (it's the same as Laravel)
I have a command for read a big XML (400Mo) and update datas in database from datas in this file, this is my code :
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->first();
if ($conditionId) {
ConditionTranslation::where(['condition_id' => $conditionId->id, 'locale' => 'fr'])->update(['name' => $name]);
$this->info(memory_get_usage());
}
}
}
}
}
So, I have to find in the XML each DescriptorUI element, the value corresponds to the mesh_id attribute of my class Condition.
So, with $conditionId = Condition::where('mesh_id', $meshId)->first(); I get the Condition object.
After that, I need to update a child of Condition => ConditionTranslation. So I just get the element DescriptorName and update the name field of ConditionTranslation
At the end of the script, you can see $this->info(memory_get_usage());, and when I run the command the value increases each time until the script runs very very slowly...and never ends.
How can I optimize this script ?
Thanks !
Edit : Is there a way with Laravel for preupdate multiple object, and save just one time at the end all objects ? Like the flush() method of Symfony
There is a solution with ON DUPLICATE KEY UPDATE
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
$keyValues = [];
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->value('id');
if ($conditionId) {
$keyValues[] = "($conditionId, '".str_replace("'","\'",$name)."')";
}
}
}
}
if (count($keyValues)) {
\DB::query('INSERT into `conditions` (id, name) VALUES '.implode(', ', $keyValues).' ON DUPLICATE KEY UPDATE name = VALUES(name)');
}
}

Laravel 5 - Display different views based on database query

I have the following database design
I have several different Documents I want a user to be able to create. Each document has its own view for the creation of the document, or the editing.
If the document they are trying to create has already been created, they should see the edit page for that document.
At the moment, I have the following
public function create(Project $project)
{
$documentTypesCreated =
$project->document()
->join('document_type', 'documents.id', '=', 'document_type.documentId')
->select('document_type.documentId', 'document_type.name')
->get();
$documentLink = $_GET['documentType'];
if($documentTypesCreated->isEmpty()){
return View::make($documentLink.'Doc.create', compact('project'));
} else {
foreach($documentTypesCreated as $documentName) {
if($documentName->name != $documentLink) {
return View::make($documentLink.'Doc.create', compact('project'));
} else {
$document = Document::find($documentName->documentId);
return View::make($documentLink.'Doc.edit', compact('project', 'document'));
}
}
}
}
Breaking this up, I am doing the following:
Firstly, I get all the Documents that have been created for a Project
$documentTypesCreated =
$project->document()
->join('document_type', 'documents.id', '=', 'document_type.documentId')
->select('document_type.documentId', 'document_type.name')
->get();
I then get the Document the user is trying to create from the URL
$documentLink = $_GET['documentType'];
So lets say that the query returns that this Project has
DocumentA
DocumentB
And the documentLink shows that I am trying to create DocumentB.
Because DocumentB has already been created, I need the edit page for this Document. Firstly, I check if the query returned and Documents
if($documentTypesCreated->isEmpty()){
return View::make($documentLink.'Doc.create', compact('project'));
} else {
}
If it didnt, it will show the create page for the chosen Document. If it did, the else statement will kick in.
Within the else statement, I loop through all the Documents the query returned
foreach($documentTypesCreated as $documentName) {
}
I then do the following, and this is where my logic is failing
if($documentName->name != $documentLink) {
return View::make($documentLink.'Doc.create', compact('project'));
} else {
$document = Document::find($documentName->documentId);
return View::make($documentLink.'Doc.edit', compact('project', 'document'));
}
If the document Name from the query is not equal to the document I am trying to create, then I show the create page for that Document. Otherwise, I show the edit page.
Now lets get back to where I chose DocumentB. I know that I have already created this Document, so I should see its edit page. However, because DocumentA is the first result returned in the query, the above statement looks like the following
if("DocumentA" != "DocumentB") {
return View::make($documentLink.'Doc.create', compact('project'));
} else {
$document = Document::find($documentName->documentId);
return View::make($documentLink.'Doc.edit', compact('project', 'document'));
}
So it is going to show the create page for DocumentB, not the edit page. If DocumentB was the first result returned, then the edit page would be displayed.
I Hope this makes sense. How can I get it displaying the correct view for the document?
Thanks
Controller
Base on your query - you may set these variables manually
$create = true;
$edit = false;
Logic
if ($query == 'any logic') {
$create = true;
$edit = false;
}else{
$create = false;
$edit = edit;
}
Then, send them over to your view.
View
#if($create == true)
//.. Show Create Form
#else
// .. Show Edit Form
#stop
Then, your view will render base the result of your query. I hope this help !

TYPO3 Extbase: How to render the pagetree from my model?

I want to create some kind of sitemap in extbase/fluid (based on the pagetree). I have loaded the pages table into a model:
config.tx_extbase.persistence.classes.Tx_MyExt_Domain_Model_Page.mapping.tableName = pages
I have created a controller and repository, but get stuck on the part wich can load the subpages as relation into my model.
For example:
$page = $this->pageRepository->findByPid($rootPid);
Returns my rootpage. But how can I extend my model that I can use $page->getSubpages() or $page->getNestedPages()?
Do I have to create some kind of query inside my model? Or do I have to resolve this with existing functions (like the object storage) and how?
I tried a lot of things but can simply figure out how this should work.
you have to overwrite your findByPid repository-method and add
public function findByPid($pid) {
$querySettings = $this->objectManager->create('Tx_Extbase_Persistence_Typo3QuerySettings');
$querySettings->setRespectStoragePage(FALSE);
$this->setDefaultQuerySettings($querySettings);
$query = $this->createQuery();
$query->matching($query->equals('pid', $pid));
$pages = $query->execute();
return $pages;
}
to get all pages. Than you can write your own getSubpages-method like
function getSubpages($currentPid) {
$subpages = $this->pagesRepository->findByPid($currentPid);
if (count($subpages) > 0) {
$i = 0;
foreach($subpages as $subpage) {
$subpageUid = $subpage->getUid();
$subpageArray[$i]['page'] = $subpage;
$subpageArray[$i]['subpages'] = $this->getSubpages($subpageUid);
$i++;
}
} else {
$subpageArray = Array();
}
return $subpageArray;
}
i didn't test this method, but it looks like this to get alle subpages.
i wonder that i couldĀ“t find a typo3 method that return the complete Page-Tree :( So i write a little function (you can use in an extbase extension), for sure not the best or fastes way, but easy to extend or customize ;)
first you need an instance of the PageRepository
$this->t3pageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
this->t3pageRepository->init();
make the init, to set some basic confs, like "WHERE deletet = 0 AND hidden = 0..."
then with this function you get an array with the page data and subpages in. I implement yust up to three levels:
function getPageTree($pid,$deep=2){
$fields = '*';
$sortField = 'sorting';
$pages = $this->t3pageRepository->getMenu($pid,$fields,$sortField);
if($deep>=1){
foreach($pages as &$page) {
$subPages1 = $this->t3pageRepository->getMenu($page['uid'],$fields,$sortField);
if(count($subPages1)>0){
if($deep>=2){
foreach($subPages1 as &$subPage1){
$subPages2 = $this->t3pageRepository->getMenu($subPage1['uid'],$fields,$sortField);
if(count($subPages2>0)){
$subPage1['subpages'] = $subPages2;
}
}
}
$page['subpages'] = $subPages1;
}
}
}
return $pages;
}

Resources