How to add many elements to database with MODX-processor - php

I have a file-uploading-processor with array output. How I can add this array to database?
That's my processor's code:
class ModCLJsonUploadProcessor extends modProcessor {
public $languageTopics = ['modcl'];
public function process() {
$file = fopen($_FILES['json-file']['tmp_name'], 'r');
$json = fread($file, $_FILES['json-file']['size']);
$objs = json_decode($json);
$english = array();
for ($i = 0; $i < count($objs); $i++) {
$english[$i] = $objs[$i]->{'name'};
}
return $this->success($english);
}
}
return 'ModCLJsonUploadProcessor';
I tried to use the native modObjectCreateProcessor, but it does not support arrays.

In order to save items into the database using a processor, the best practice would be to create a schema and save the given data as objects in the database. This allows you to then later retreive the items (objects) in other processors or snippets using xPDO.
For a basic explenation/how to on creating a schema and interacting with the custom objects have a look at the "Developing an extra in MODX Revolution" doc here

Related

How to separate transforming/mapping from db results of Repository methods?

How to transform data (from Repository/Entity to PersonData) in proper way in Symfony?
Code like below is useful for me. I using this metod often and make work with arrays of PersonData objects. But I'm aware that it brakes SOLID principles (Repository class filter/transform data but should only get data from db).
If I separate filling PersonData my other services will be grow some extra lines of code because they need to do every time what actual findActive() is doing.
// src/Repository
/**
* #return \App\ValueObject\PersonData[]
*/
public function findActive(): array
{
$entities = $this->findBy(['active_status' => true]);
if (! $entities) {
return [];
}
$data = [];
foreach ($entities as $entity) {
$data[$entity->getId()] = new PersonData(
$entity->getName(),
$entity->getScore(),
$entity->getValue()
);
}
return $data;
}

PHP dynamic multidimensional array creation

I'm scanning a folder and it's subfolders for files with PHP. I want to store the folders and files in a PHP array so I can create a treeview in another page. This is the format I get files paths in:
/home/project/index.php
/home/project/folder/myclass.php
/home/project/folder/myclass2.php
/home/project/folder/subfolder/anotherclass.php
I want to get these files in the following array:
[home][project] = array('index.php')
[home][project][folder] = array(myclass.php, myclass2.php)
[home][project][folder][subfolder] = array(anotherclass.php)
Note that the folder structure can change at any point. How can I achieve this?
The easiest way would be to use the built in (SPL) DirectoryIterator class and a simple recursive function.
An untested example:
public function directoryToArray($directoryPath)
{
$items = new DirectoryIterator($directoryPath);
$data = array();
foreach($items as $item) {
$name = $item->getFileName();
if ($item->isFile()) {
$data[] = $name;
}
else if ($item->isDir()) {
$data[$name] = directoryToArray($item->getPath());
}
}
return $data;
}

Kohana ORM - has many through models stored in parent model

I had many problems with has_many-through relationships but finally I found nice example here which solved most of my problems. However, according to code presented below I have couple questions.
firstly, code:
$artists = ORM::factory('artist')->find_all();
foreach ( $artists as $artist )
{
foreach ( $artist->media->find_all() as $m )
{
echo $m->name;
}
}
1) This example is probably controller. What if I want to store media in $artists to send one variable to view? Is it possible to store media as media property in artist object? (I mean for example $artists[0]->media[0]->name)
2) Is it possible to completely load $artists without this loop?
1) If I understood correctly, you need to get some element from medias
$artists = ORM::factory('artist')->find_all()->as_array();
$media = $artists[0]->media->find_all()->as_array(); // media of first artist
$name = $media[0]->name;
2) See above $artists is an array of ORM objects
Following my comment, this is what I'd do.
class Model_Artist extends ORM {
///
/// Whatever you have now
///
private $_media_cache = NULL;
public function media($key = NULL)
{
// Check cache
if($this->_media_cache == NULL)
{
$this->_media_cache = $this->media->find_all();
}
if($key !== NULL)
{
// Use Arr::get in case index does not exist
// Return empty media object when it does not exist so you can
// 'harmlessly' ask for its properties
return Arr::get($this->_media_cache, $key, ORM::factory('Media'));
}
return $this->_media_cache;
}
}
Callable as
$artists[0]->media(0)->name

PHPExcel - Using example read fiter

I'm just getting started with PHPExcel. My very large spreadsheets cannot be loaded whole into memory (memory fail). To only load the parts of the worksheet I need, I'm trying to use the MyReadFilter code that was provided in the documentation, but the code is a bit above me and I'm hoping someone can help me understand it.
From the PHPExcel documentation, here's the function:
class ReadFilter implements PHPExcel_Reader_IReadFilter
{
private $_startRow = 0;
private $_endRow = 0;
private $_columns = array();
/** Get the list of rows and columns to read */
public function __construct($startRow, $endRow, $columns) {
$this->_startRow = $startRow;
$this->_endRow = $endRow;
$this->_columns = $columns;
}
public function readCell($column, $row, $worksheetName = '') {
// Only read the rows and columns that were configured
if ($row >= $this->_startRow && $row <= $this->_endRow) {
if (in_array($column,$this->_columns)) {
return true;
}
}
return false;
}
}
I'm using the following lines to invoke PHPExcel
// Get the selected Excel file, passed from form
$testFile = $_FILES['upload_test']['tmp_name'];
// Identify the file type of the selected file
$inputFileType = PHPExcel_IOFactory::identify($testFile);
// Create a reader object of the correct file type
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
// Instantiate the filter class and apply it to the reader object
$filterSubset = new ReadFilter(1,1000,range('A','Z'));
$objReader->setReadFilter($filterSubset);
// Load the selected file into the reader
$objWorkbook = $objReader->load($testFile);
I am retrieving data from the resulting worksheet object using this syntax:
$someValue= $objWorkbook->getSheet($idx)->getCell('B11')->getCalculatedValue();
I'm sure I'll have other questions as I go, but my initial one is about invoking the function. If I change the above line from:
$filterSubset = new ReadFilter(1,1000,range('A','Z'));
to:
$filterSubset = new ReadFilter(1,1000,range('A','AA')); //Last column changed
the entire read fails. I actually only need calculated values from column B, but that column has references as far over as column AS, so I need to read them as well. Can someone please tell me how to use this function to read past column Z, or to modify it? Ideally, what I'd like is to just read the contents of about a dozen columns spread out from B to AS, but I can't figure that out either.
Thanks much for any help.
range('A','AA'); is not valid try creating your own custom range
Example
echo "<pre>";
print_r(xrange('AA', 'ZZ'));
Function Used
function xrange($start, $end, $limit = 1000) {
$l = array();
while ($start !== $end && count($l) < $limit) {
$l[] = $start;
$start ++;
}
$l[] = $end;
return $l;
}
See Live Demo
range('A','AA) isn't a valid range.... PHP's range function doesn't assume that AA follows Z. Try using column numbers instead, using PHPExcel's columnIndexFromString() and stringFromColumnIndex() static methods in the PHPExcel_Cell class to convert 27 to AA and vice versa (watch out for the base value 0 or 1 though).

Copy a Doctrine object with all relations

I want to copy a record with all his relations.
I'm trying with:
$o = Doctrine::getTable('Table')->Find(x);
$copy = $object->copy();
$relations = $o->getRelations();
foreach ($relations as $name => $relation) {
$copy->$relation = $object->$relation->copy();
}
$copy->save();
This code doesn't works, but I think it's on the way.
I never could get the deep copy function to operate correctly.
I manually coded a deep copy function for one of my models like this
public function copyAndSave ()
{
$filters = array('id', 'created');
$survey = $this->copy();
$survey->Survey_Entries = new Doctrine_Collection("Survey_Model_Entry");
$survey->Assignment_Assignments = new Doctrine_Collection("Assignment_Model_Assignment");
$survey->Survey_Questions = new Doctrine_Collection("Survey_Model_Question");
$survey->save();
foreach ($this->Survey_Questions as $question)
{
$answers = $question->Survey_Answers;
$newQuestion = $question->copy();
$newQuestion->survey_surveys_id = $survey->id;
$newQuestion->save();
$newAnswers = new Doctrine_Collection("Survey_Model_Answer");
foreach($answers as $answer)
{
$answer = $answer->copy();
$answer->save();
$answer->survey_questions_id = $newQuestion->id;
$newAnswers->add($answer);
}
$newQuestion->Survey_Answers = $newAnswers;
$survey->Survey_Questions->add($newQuestion);
}
return $survey->save();
}
You can read about copy() here. It takes an optional parameter $deep:
$deep
whether to duplicates the objects targeted by the relations
So
$copy = $object->copy(true);
should do it.
Sorry if I'm resurrecting this thread...
I found myself in search of a solution recently where I needed to copy a record and retain the references of the original. A deep copy $record->copy(true) copies the references, which was no good for me. This was my solution:
$record = Doctrine_Core::getTable('Foo')->find(1);
$copy = $record->copy();
foreach($record->getTable()->getRelations() as $relation) {
if ($relation instanceof Doctrine_Relation_Association) {
$ids = array();
foreach ($relation->fetchRelatedFor($record) as $r) {
$ids[] = $r->getId();
}
$copy->link($relation->getAlias(), $ids);
}
}
if ($copy->isValid()) {
$copy->save();
}
Hope this helps :)
This is how i done, but some fix is needed.
$table = $entidade->getTable();
$relations = $table->getRelations();
foreach($relations as $relation => $data) {
try {
$entity->loadReference($relation);
} catch(Exception $e) {
die($e->getMessage());
}
}
I am using Symfony1.4.1 and that uses Doctrine 1.2.1 (I think).
I have been trying to make a function that did all the above myself, when I found one that already exists.
Try this in any function and look at the results:
$tmp=$this->toArray(TRUE);
var_dump($tmp);
$this->refreshRelated();
$tmp=$this->toArray();
var_dump($tmp);
$tmp=$this->toArray(TRUE);
var_dump($tmp);
exit();
I am going to try two different things:
A/ put $this->refreshRelated() into the constructor of all my model objects.
B/ write a function that takes an array depicting the object graph that I want populated. Calling the function refereshRelatedGraph($objectGraphArray). With the right structure of the array (having all the appropriate relation names at each level), I could control which relations get populated and which don't. One use for this is to populate only children, not parent relations. The other is for when a ERD/Schema/ObjectGraph has an element that is 'owned' by more than one object (many to many, other special circumstances that I have), I could control which side of the relationships get pre(non lazy) loaded.

Categories