Laravel help for optimize command script - laravel

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)');
}
}

Related

Api platform add or update

Good afternoon I am adding data in via POST method in PLATFORM API can I make this method work like adding or updating data.
So that when the data is already there for the object, it will simply update the pinOrder field.
My input:
{
"chat": "/api/chats/01FVKRYXMMTHKJ2EZB02F4FZ3Z",
"pinOrder": 3
}
Insert or update (upsert) is not available in Api Platform. However, you can achieve this behavior with a custom (or decorated) Data Persister.
https://api-platform.com/docs/core/data-persisters/
In the persist method of the data persister you could manually check if an item matching your criteria does already exist and, if yes, update this one instead of persisting a new one.
You can use PRE_WRITE event. For exemple, an order item quantity.
public static function getSubscribedEvents(): array
{
return [
KernelEvents::VIEW => [
'updateExistingItemQuantity', EventPriorities::PRE_WRITE,
],
];
}
public function updateExistingItemQuantity(
ViewEvent $event
): void {
$item = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$item instanceof MyItemObject || Request::METHOD_POST !== $method) {
return;
}
// find duplicateItem
if ($duplicateItem) {
$duplicateItem->setQuantity("UPDATED QUANTITY");
// save $duplicateItem
$event->setControllerResult($duplicateItem);
}
}

import phpexcel codeigniter except current cell value

i want to import from excel using php excel from my codeigniter with current cell containt current text
cell1
cell2
A
1
B
2
C
3
i want just cell except B in cell1 to insert database
my controller
public function import_excel(){
if (isset($_FILES["fileExcel"]["name"])) {
$path = $_FILES["fileExcel"]["tmp_name"];
$object = IOFactory::load($path);
foreach($object->getWorksheetIterator() as $worksheet)
{
$highestRow = $worksheet->getHighestRow();
$highestColumn = $worksheet->getHighestColumn();
for($row=2; $row<=$highestRow; $row++)
{
$cell1= $worksheet->getCellByColumnAndRow(0, $row)->getValue();
$cell2= $worksheet->getCellByColumnAndRow(1, $row)->getValue();
$temp_data[] = array(
'cell1' => $cell1,
'cell2' => $cell2,
);
}
}
if($cell1 == 'B'){
}else{
$this->load->model('M_Admin');
$insert = $this->M_Admin->insert($temp_data);
}
but this failed and data still insert. please help me and many thanks you for help.
I never use phpexcel before, but if it's array and consider that $cell1 is a string/text, I guess you can try to use this:
for($row=2; $row<=$highestRow; $row++)
{
$cell1= $worksheet->getCellByColumnAndRow(0, $row)->getValue();
$cell2= $worksheet->getCellByColumnAndRow(1, $row)->getValue();
//cell value you want to hide
if ($cell1 == 'B') {
$cell1 = 'xxx'; //overwrite that value into something
}
$temp_data[] = array(
'cell1' => $cell1,
'cell2' => $cell2,
);
}
note: I'm using codeigniter 3

Searching value in already cache data from database in 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.

options array in Joomla session?

I've been analyzing joomla session and I came across a few problems. One of the problems is the session name.
See this code:(seesion.php#894)
protected function _setOptions(array $options)
{
// Set name
if (isset($options['name']))
{
session_name(md5($options['name']));
}
// Set id
if (isset($options['id']))
{
session_id($options['id']);
}
// Set expire time
if (isset($options['expire']))
{
$this->_expire = $options['expire'];
}
// Get security options
if (isset($options['security']))
{
$this->_security = explode(',', $options['security']);
}
if (isset($options['force_ssl']))
{
$this->_force_ssl = (bool) $options['force_ssl'];
}
// Sync the session maxlifetime
ini_set('session.gc_maxlifetime', $this->_expire);
return true;
}
My problem is with the $options array , I add this to the script:
print_r($options);
the result was: Array ( [name] => 266e79f0eac297f66eaf7926636f03fa [expire] => 900 )
where did this element come from ? I mean is there a value that will allow me to do this:
md5('value');
and get the same [name] element
Hey i found the answer for this.
The session value is calculated as following.
$hash = md5(md5($secret.'site'));
where $secret is defined in the configuration file.
use following code to get the session value.
include_once(dirname(dirname(FILE)).DIRECTORY_SEPARATOR.'configuration.php');
$config = new JConfig;
$secret = $config->secret;
$hash = md5(md5($secret.'site'));
So for you the value of name variable comes from md5($secret.'site') which is session value. and if you take md5 again it will give you the session cookie value.

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