I am working in a import method, that save the data od an *.csv into a table, but i verify if this data already exist in table, if this is true, i would redirect to a view or to another method, but dont redirect!
In the line
//comparing if the data of file exists in the table
if exists data i try to make a return:
return view ('catinvistas.ingresos.mensaje');
and must to finish all the following proccess, right?
public function import()
{
Excel::load('storage\app\reloj.csv', function($reader) {
foreach ($reader->get() as $marcacion) {
//file data
$archivo=(int)$marcacion->id_voluntario;
$archivo_fecha=$marcacion->marcacion;
//table data
$tabla_c1 = DB::table('marcaciones')->where('id_voluntario', $marcacion->id_voluntario)->first();
if (!empty($tabla_c1)){
$tabla=(int)$tabla_c1->id_voluntario;
$tabla_fecha=$tabla_c1->marcacion;
//comparing if the data of file exists in the table
if (($tabla==$archivo) && ($tabla_fecha==$archivo_fecha))
{
//dd ($tabla,$tabla_fecha,$archivo,$archivo_fecha);
return view ('catinvistas.ingresos.mensaje');
}
}
//insert all data of the file into the table
Marcaciones::create([
'id_voluntario' =>$marcacion->id_voluntario,
'marcacion' => $marcacion->marcacion
]);
}
});
$data=Marcaciones::all();
return view('catinvistas.ingresos.importacion')->with('data',$data);
}
Related
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)');
}
}
I have a intermediary table in which I want to save sbj_type_id and difficulty_level_id so I have setup this:
$difficulty_level = DifficultyLevel::find(5);
if ($difficulty_level->sbj_types()->sync($request->hard, false)) {
dd('ok');
}
else {
dd('not ok');
}
Here is my DifficultyLevel.php:
public function sbj_types() {
return $this->belongsToMany('App\SbjType');
}
and here is my SbjType.php:
public function difficulty_levels() {
return $this->hasMany('App\DifficultyLevel');
}
In the above code I have dd('ok') it's returning ok but the database table is empty.
Try to change
return $this->hasMany('App\DifficultyLevel');
to
return $this->belongsToMany('App\DifficultyLevel');
The sync() method takes an array with the id's of the records you want to sync as argument to which you can optionally add intermediate table values. While sync($request->hard, false) doesn't seem to throw an exception in your case, I don't see how this would work.
Try for example:
$difficulty_level->sbj_types()->sync([1,2,3]);
where 1,2,3 are the id's of the sbj_types.
You can read more about syncing here.
I need file upload field to be required for both Create and Update actions, and the required validation and validation of types to be performed in both cases.
This is how my form looks like (Note: It's a form, not an Active Record model):
<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\base\Object;
use yii\helpers\FileHelper;
class MyCustomForm extends Model
{
public $file_image;
public function rules()
{
return [
[
[['file_image'], 'file', 'skipOnEmpty' => false, 'extensions' => 'jpg, jpeg, png, bmp, jpe']
]
];
}
public function scenarios()
{
$scenarios = parent::scenarios();
//Scenarios Attributes that will be validated
$scenarios['action_add'] = ['file_image'];
$scenarios['action_edit'] = ['file_image'];
return $scenarios;
}
}
And this is how my controller actions looks like.
The Create action works as expected (on POST request I'm taking the Uploaded File with UploadedFile::getInstance command)
public function actionCreate()
{
$model_form = new MyCustomForm(['scenario' => 'action_add']);
if (Yii::$app->request->isPost && $model_form->load(Yii::$app->request->post())) {
$model_form->file_image = \yii\web\UploadedFile::getInstance($model_form, "file_image");
if($model_form->validate()) {
if(isset($model_form->file_image)){
//I'm uploading my image to some cloud server here
//creating corresponding $model_entity for database, fill with the data from the form and save it
$model_entity->save();
}
}
}
}
But I'm facing with an issue when doing the same on Update action. In database I have the URL of image that is on third party cloud server and I can access it and display the image in my form (so GET request on Update works, I'm getting the corresponding entity from database and fill the form with data). But for POST, file validation is failing, if I don't have file assigned in the model and the POST request for Update is not working.
public function actionUpdate($id)
{
$model_entity = $this->findModel($id);
$image_URL = //I'm having URL to corresponding image here;
$model_form = new MyCustomForm(['scenario' => 'action_edit']);
$model_form_data = [$model_form->formName() => $model_entity->attributes];
$model_form->load($model_form_data);
if (Yii::$app->request->isPost && $model_form->load(Yii::$app->request->post())) {
//if we upload image again this will work
//NOTE: I have another text fields in the form and If I only change them
//and if I don't change the file image, the following result will return NULL and validation will fail
$file_uploaded_image = \yii\web\UploadedFile::getInstance($model_form, "file_image");
if(isset($file_uploaded_image)){
//new image is uploaded on update, this scenario will be OK
} else {
//no image is uploaded on update, this scenario will fail
}
if($model_form->validate()) {
//this will fail if I don't upload image on Update
}
}
}
I have tried many things in Update action, before validation, in order to find a workaround to get the image and validation to not fail. For example:
$dataImg = file_get_contents($image_URL);
$model_form->file_image = $dataImg;
or trying to do get with temporary file:
$dataImg = file_get_contents($dataImg);
$filePath = \yii\helpers\FileHelper::createDirectory("/images/tmp/test.png", 777);
file_put_contents($filePath, $dataImg);
$model_form->file_image = $filePath;
But none of them is working. Is there any solution to this scenario?
Note that I will have to use a Froms (as above) and not the ActiveRecord, since my real project is more complex that example listed.
Write this code in your Model(MyCustomForm) :
class MyCustomForm extends Model
{
public $file_image;
public function rules()
{
return [
[['file_image',],'required','on'=>['create','update']],
[['file_image'], 'file','extensions' => 'jpg, jpeg, png, bmp, jpe'],
];
}
}
Write this code in your actionCreate() :
$model_form = new MyCustomForm();
$model_form->scenario = "create";
Write this code in your actionUpdate() :
$model_form = new MyCustomForm();
$model_form->scenario = "update";
Or you can add scenario by this :
$model_form = new MyCustomForm(['scenario' => 'create']);
I have tried this and it is working.
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 !
I'm trying to save a PDF file directly to db oracle (not a path) by stored_procedure function in codeigniter framework
i modified the _execute() function at oci8_driver.php file and add this
protected function _execute($sql)
{
$this->stmt_id = FALSE;
$this->_set_stmt_id($sql);
$blob=FALSE;
$myarray=array();
$myarray = $this->binds;
if (is_array($myarray)) {
foreach ($myarray as $value) {
if ($value['type'] === 113 )
{
$this->lob = oci_new_descriptor($this->conn_id, OCI_D_LOB);
$blob=TRUE;
} }
...........
..................
.....
$exec_worked = ociexecute($this->stmt_id, $this->_commit);
if (is_array($myarray)) {
foreach ($myarray as $value) {
if ($value['type'] === 113 )
{
oci_execute($this->stmt_id, OCI_DEFAULT);
if($blob)
{
$this->lob->savefile($value['value'] );
oci_commit($this->conn_id);
}
}
}
and modify the _bind_param() function in the same file adding this lines
if ($param['type'] === 113)
oci_bind_by_name($this->stmt_id , $param['name'], $this->lob, $param['length'], OCI_B_BLOB);
but the problem is it save files twice ...i test the procedure itself and the model function all show that it executed one time, i don't know where the duplication occur
is my modification cause the problem and what i should do?
Call $this->db->simple_query() instead of $this->db->query() and/or $this->db->stored_procedure().