Auto-generate isCrossRef in schema.xml - propel

I'm currently developing a modular site with silex, propel and twig.
It is my intention to create an installer project on top of it so I can easily create new projects based on my "core" project.
My database has some many-to-many table which require the isCrossRef attribute in my schema.xml. When reverse engineering my MySql database Propel can't determine which tables are crossRef. I get that, but now I was wondering if I could alter the schema.xml generation.
Lets says If I add a comment to the tables that need this isCrossRef attribute, then where in the Propel source code would I be able to read out this comment and add the required IsCrossRef to the generated schema.xml ?

After reading some of the source code I found the answer myself :
If u want to accomplish this u will need the modify the file : MysqlSchemaParser.php, located at : propel1/generator/lib/reverse/mysql (when installed with composer)
Alter the recordset at line 99 to :
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
$name = $row[0];
$type = $row[1];
if ($name == $this->getMigrationTable() || $type != "BASE TABLE") {
continue;
}
/*
Edit : Find out if table isCrossRef
*/
$commentStmt = $this->dbh->query("show table status like '".$name."'");
$commentRow = $commentStmt->fetch(PDO::FETCH_OBJ);
$isCrossRef = (strtolower($commentRow->Comment) == 'iscrossref');
/*
End of edit
*/
if ($task) {
$task->log(" Adding table '" . $name . "'", Project::MSG_VERBOSE);
}
$table = new Table($name);
$table->setIdMethod($database->getDefaultIdMethod());
$table->setIsCrossRef($isCrossRef); /*EDIT : set is crossref to true*/
$database->addTable($table);
$tables[] = $table;
}

Related

Doctrine Statement: Select from Database with uuid (value isnt readable)

in Symfony i need access to another Database from another Project. So i created another entityManager for this connection.
Now i want read some Data where id field is uuid.
the statement looks like this:
$entityManager = $this->doctrine->getManager('myProject');
$connection = $entityManager->getConnection();
$statement = $connection->prepare(
'SELECT * FROM salutation '
);
$resultSet = $statement->executeQuery();
dd($resultSet->fetchAll());
But the id value is not readable.
"id" => b"\x0E2#\x05P\x08Gó€dˆk§\vè\x05"
Is there a way to tell Doctrine to handle this field as Uuid?
Thanks for your Help.

Allow laravel to filter requests based on field types

So i have 300 different fields in my form generating from a database.These fields can be either a drop-down or text field which need to be saved in two different databases.
To get all the fields that are dropdown i will have to use
$request->input('name')
$request->input('email')
$request->input('username')
and 100 other fields.
rather than doing that and to filter requests based on input types
if(input_type==text){
save to this table
}
else if (input type==select){
save to this table
}
User laravel DB class for that.
Consider below example .
$data = array();
if(input_type==text){
$data['field1'] = 'somevalue';
}
else if (input type==select){
$data['field2'] = 'somevalue';
}
$Insert = DB::table('TABLE_NAME')->insert($data);
Make sure that table have detault value for fields which you are not inserting.
You can use something like this. I am guessing you have two different Model class for store in the database
$firstTableFields = [ 'field1', 'field2', 'field3'];
$secondTableFields = [ 'field4', 'field5', 'field6'];
$firstModel = new Model($request->only($firstTableFields));
$firstModel->save();
$secondModel = new Model($request->only($secondTableFields));
$secondModel->save();

Laravel 5 - relationships and handling data

I have a system whereby you can create Documents of different types. Initially, I had a new Model for each Document, but I don't think this is the best way because it can get messy fast. So what I wanted to do is make a generic Documents model, and have individual documents come from this. I have come up with the following type of design
So a Document can have one DocumentA and one DocumentB. DocumentA and DocumentB can only ever be created once per project which is why I have this relationship. Now each form for each document has an upload button, where supporting documents can be uploaded alongside the generated document. So Documents can have one to many FileUploads.
This is where I am confused. A person visits my portal and selects the option to create DocumentA. A form is now displayed to them which looks something like the following
So they enter the data for DocumentA, upload supporting documents, and then click submit.
Now I am thinking about how this can be handled within Laravel.
From what I understand, it will be something like the following
public function store(Request $request, Project $project)
{
$document = new Documents();
$document->documentName = 'Something';
$document->documentA = new DocumentA();
$document->documentA->startDate = Input::get('startDate');
$document->documentA->endDate = Input::get('endDate');
$document->documentA->notes = Input::get('notes');
if (Input::hasFile('filePath')) {
$files = Input::file('filePath');
foreach($files as $file) {
$fileString = "";
$file->move(public_path('uploads'), $file->getClientOriginalName());
$fileString .= public_path('uploads') . '/' . $file->getClientOriginalName();
$document->fileUpload = new FileUploads();
$document->fileUpload->filename = $file->getClientOriginalName();
$document->fileUpload->mime = $file->getClientOriginalExtension();
$document->fileUpload->filepath = $fileString;
$document->fileUpload->documentId = $document->id;
}
}
$document->save();
return Redirect::route('projects.documentA.edit', compact('project', 'documents'));
}
Really, looking for advice as to whether I am designing this correctly, and whether I am handling it correctly within Laravel. I am going to end up with many different Documents, each of them accepting different input.
Any advice appreciated.
Thanks
you want to create different tables for each doc? like you showed above for A and B. It will become messy. Why do not you just manage this in one table by using some identifier col?
If you create one table for documents, one for fileUploads then you would create relationship between them like so
File upload model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class File extends Model
{
/**
* each file belongs to a document
*/
public function document()
{
return $this->belongsTo('App\Document', 'foreign_key', 'primary_key');
}
}
Document model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Document extends Model
{
/**
* document has multiple files
*/
public function files()
{
return $this->hasMany('App\File', 'foreign_key', 'primary_key');
}
}
Then you can access the records like this
$documents->files()->where('id', 1)->get();
//gives file associated with document id 1

Laravel - CreateMany if not exists

I have a table that stores tags name as "tag"
tag
id->Integer(unique)
title->String;
url->string;(unique)
Also I have a table to store places named as place
place
id->Integer(unique)
title->string
latitude->string
longtitue->string
A place may have many tags, here is my place_tag table
place_tag
id->Integer(unique)
tag_id->Integer
place_id->Integer
when I try to update place I need to do this
1- check all tags posted.
2- add them to "tag" db if not created before
3- write relationship with tag and place
But I think Laravels ORM can handle it, I'm walking around but can't find a good solution.
Please see my update procedure what am I doing wrong.
public function update($id)
{
$place=Place::findOrFail($id);
$place->fill(Input::all());
$place->save();
$tags=explode(',',Input::get('tags'));
$tags_data=array();
foreach($tags as $tag) {
$tags_data[]=new Tag(array('title'=>$tag,'url'=>$tag));
}
$place->tags()->detach();
$place->tags()->saveMany($tags_data);
return Redirect::to('admin/places');
}
You can do it this way:
$tagIds = [];
foreach ($tags as $tag) {
$tag = trim($tag);
if ($tag == '') {
continue;
}
$fTag = Tag::firstOrCreate( [ 'title' => $tag, 'url' => $tag ] );
$tagIds[] = $fTag->id;
}
$place->tags()->sync($tagIds);
I assumed one Tag can be set to many Places (n:n relationship), so first you basically find tags and if it doesn't exist you create it and then using sync you synchronize relationship table (insert or remove data from pivot when necessary)

Replacing "product name" with "Item + productId" when product is added in Magento via admin panel

I want to auto generate product names in Magento.
When I'm going to add a product, for the product name I will type some string.
When I save the product, I want the product name to be automatically generated such that the product name becomes Item."productId".
Answering assuming that OP wants to incorporate the auto-increment value from the entity table into business data. This is generally not a great idea.
This is an interesting task which can be easily accomplished with Magento's EAV implementation - particularly when working in the catalog module. First, some background.
When an EAV entity is saved, it has a nice, neat array of key => value pairs which represent the attributes and attribute values for that entity:
Mage_Catalog_Model_Product->_data['attribute_code'] = 'attribute value';
During the save process, the EAV resource model takes this array and iterates over it. For each attribute, identified by its code (attribute_code in the above example) and its entity (catalog_product in the case of products), the configuration for the attribute itself is loaded. Of particular importance is the "backend model" for an attribute, as it is invoked to do pre- and post-processing of/relating to the value.
In the current case, there is a piece of information which will not be present when we are saving the attribute, at least, not in a way in which we can use it: the new product id. This can be used to adjust the original value as part of the save process.
It's always nice to have an example from the core, so, refer to the price attribute and its backend model, Mage_Catalog_Model_Product_Attribute_Backend_Price which can be seen in the eav_attribute table:
SELECT `attribute_code`, `backend_model`
FROM `eav_attribute`
LEFT JOIN `eav_entity_type` USING (`entity_type_id`)
WHERE `attribute_code` = 'price';
#+----------------+-----------------------------------------+
#| attribute_code | backend_model |
#+----------------+-----------------------------------------+
#| price | catalog/product_attribute_backend_price |
#+----------------+-----------------------------------------+
#1 row in set (0.00 sec)
When a product is saved, the price attribute's backend_model is instantiated and (in this case) the afterSave() method is called. Incidentally, this method is what updates pricing by conversion rate for website-scoped pricing. This same approach can be used to modify the name attribute.
The following setup script will add the backend model:
<?php
$installer = Mage::getResourceModel('catalog/setup','default_setup');
$installer->startSetup();
$installer->updateAttribute(
'catalog_product',
'name',
'backend_model',
'custom/product_attribute_backend_name'
);
$installer->endSetup();
The corresponding afterSave() method should do the trick:
public function afterSave($object)
{
$value = $object->getData($this->getAttribute()->getAttributeCode());
$origData = $object->getOrigData();
$origValueExist = $origData && array_key_exists($this->getAttribute()->getAttributeCode(), $origData);
//don't do this in case of update
if ($object->getStoreId() != 0 || !$value || $origValueExist) {
return $this;
}
//append autoinc id
$newValue = $value .'.'. $object->getId(); // or whatever
//assume global store, otherwise the stated need is getting weird!
$object->addAttributeUpdate($this->getAttribute()->getAttributeCode(), $newValue, 0);
return $this;
}
If you're doing this from the admin panel product edit screen, you're going to have to remove the "Required" class from the "Name" field so you can save it without the name. This means overriding the Edit form to replace that field specifically. Then you'll have to overload the save-related methods on the product model (or you can do it from the controller), but the child will have to generate the name on save before it goes to the database.
For example:
class Module_Catalog_Model_Product extends Mage_Catalog_Model_Product
{
protected function _beforeSave()
{
parent::_beforeSave();
$productName = 'Item' . $this->getId();
if (!$this->getId() && !$this->getName())
{
$this->setName('Item Unnamed');
} elseif ($this->getId()) && strcasecmp($this->getName(), $productName) <> 0)
{
$this->setName($productName);
}
}
}
The only problem with this is that it requires two saves. If you want to have it work on the fly, you'll have to do a second save using the _afterSave() method. Or, once again, you can do it from the controller.
I would use a Magento Event to do this:
Since Models in Magento have an event prefixes (just take a look at Mage_Catalog_Model_Product and look for $_eventPrefix, for our current model the eventPrefix is set to catalog_product.
If you now take a look at Mage_Core_Model_Abstract and search for _eventPrefix. You see that eventPrefix are found in _beforeLoad, _afterLoad, _beforeSave, _afterSave and a few others. In these methods you can see an event is dispatched using something as below:
Mage::dispatchEvent($this->_eventPrefix.'_save_before', $this->_getEventData());
This means you have an event available called catalog_product_save_before. With this event you can hook into Magento at that time and do your thing, change the field in this case, and Magento handles the rest.
Take a look at http://www.magentocommerce.com/wiki/5_-_modules_and_development/0_-_module_development_in_magento/customizing_magento_using_event-observer_method for more information how to use these events and turn them into a module. If you don't know how to build modules for Magento and want to learn, there are some awesome on-demand video's for free: http://www.magentocommerce.com/training/on-demand
First I want to thanks to all users which write in the topic. Thanks a lot of guys!
I did it, but I make it easier. (because I have very basic knowledge in Magento and it would toke more time)
So... With my colegues decided to make it with php/jquery/ajax.
First we create one single php file, which return the last id:
<?php
header('Access-Control-Allow-Origin: *');
require_once 'app/Mage.php';
umask(o);
Mage::app('default');
Mage::getSingleton('core/session', array('name'=>'frontend'));
$model = Mage::getModel('catalog/product'); //getting product model
$collection = $model->getCollection(); //products collection
foreach ($collection as $product) //loop for getting products
{
$id=$product->getId();
}
if($id)echo $id+1; //id of product
else{
echo 0;
}
?>
After step one I set the value of input (i.e. I auto generate the name):
if($j('#name').val()=='' && window.location.href.indexOf("admin/catalog_product/new/") > -1) {
$j.post('http://www.website.com/file.php', function(data) {
$j('#name').val('Item №'+data);
});
}
Thanks again for help.
Best Regards,
Jordan!

Resources