Magento Entwicklung: Unterschied zwischen den Versionen

Aus Vosp.info
Wechseln zu:Navigation, Suche
(app code - die eigentliche code logik inklusive datenbank zugriff)
(allgemein Backendend)
 
(57 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
 +
[[magento extension: anc_image]] - eine einfache Extension inkl. datenbanktabelle
 +
 
= Entwicklung =
 
= Entwicklung =
 
* [https://inchoo.net/ecommerce/magento/how-to-create-a-new-product-type-in-magento/ how-to-create-a-new-product-type-in-magento]
 
* [https://inchoo.net/ecommerce/magento/how-to-create-a-new-product-type-in-magento/ how-to-create-a-new-product-type-in-magento]
Zeile 4: Zeile 6:
  
 
== globale Funktionsaufrufe ==
 
== globale Funktionsaufrufe ==
 +
 +
=== Cache Löschen ===
 +
<source lang="php">
 +
Mage::app()->cleanCache();
 +
</source>
 +
=== eingeloggt ===
 +
<source lang="php">
 +
if(Mage::getSingleton('customer/session')->isLoggedIn()) {
 +
$customer_id = Mage::getSingleton('customer/session')->getCustomer()->getId();
 +
 +
} else if(Mage::app()->getStore()->isAdmin()) {
 +
$admin_id = Mage::getSingleton('admin/session')->getUser()->getId();
 +
}
 +
</source>
 +
 +
=== anderes ===
 +
 
dieses sind allgemeine Funktionsaufrufe, die nahe zu überall (oder Kontex bezogen) aufgerufen werden können
 
dieses sind allgemeine Funktionsaufrufe, die nahe zu überall (oder Kontex bezogen) aufgerufen werden können
  
Zeile 11: Zeile 30:
 
  */
 
  */
 
$post_get_array = Mage::app()->getRequest();
 
$post_get_array = Mage::app()->getRequest();
 +
  
 +
/**
 +
* aktuelle url
 +
*/
 +
Mage::helper('core/url')->getCurrentUrl();
 +
</source>
 +
 +
==== Session ====
 +
<source lang="php">
 
/**
 
/**
 
  * hole aktuelle Session
 
  * hole aktuelle Session
Zeile 17: Zeile 45:
 
$session = Mage::getSingleton('checkout/session');
 
$session = Mage::getSingleton('checkout/session');
  
// was in die session schreiben
+
// was in die session schreiben mit den magischen Funktionen
 
Mage::getSingleton('checkout/session')->setName('Value');
 
Mage::getSingleton('checkout/session')->setName('Value');
 +
Mage::getSingleton('checkout/session')->set<Variablenname>('Value');
  
// was aus der session holen
+
// was aus der session holen mit den magischen Funktionen
 
Mage::getSingleton('checkout/session')->getName('Value');
 
Mage::getSingleton('checkout/session')->getName('Value');
 +
Mage::getSingleton('checkout/session')->get<Variablenname>('Value');
  
/**
 
* aktuelle url
 
*/
 
Mage::helper('core/url')->getCurrentUrl();
 
 
</source>
 
</source>
 +
 
=== Model ===
 
=== Model ===
 
* http://www.magentocommerce.com/wiki/1_-_installation_and_configuration/using_collections_in_magento
 
* http://www.magentocommerce.com/wiki/1_-_installation_and_configuration/using_collections_in_magento
Zeile 59: Zeile 86:
 
$quote = Mage::getSingleton('checkout/session')->getQuote();
 
$quote = Mage::getSingleton('checkout/session')->getQuote();
  
 +
            // Mage::registry('product');
 
             if (Mage::registry('current_product')) {
 
             if (Mage::registry('current_product')) {
 
                 $this->_product = Mage::registry('current_product');
 
                 $this->_product = Mage::registry('current_product');
Zeile 71: Zeile 99:
 
$getParamId = Mage::app()->getRequest()->getParam('id')
 
$getParamId = Mage::app()->getRequest()->getParam('id')
 
</source>
 
</source>
 +
 +
=== backend ===
 +
<source lang="php">
 +
// ist mensch admin
 +
Mage::app()->getStore()->isAdmin();
 +
$admin_id = Mage::getSingleton('admin/session')->getUser()->getId();
 +
</source>
 +
 +
 +
==== Backend Tables (Grid) ====
 +
[[anc_lib_timetables_backend|Beispiel für Backend Grids]]
  
 
=== Block .... schnipsel ===
 
=== Block .... schnipsel ===
Zeile 98: Zeile 137:
 
* [http://www.codesprint.de/blog/magento-statischen-block-ausgeben/ Magento: Statischen Block ausgeben]
 
* [http://www.codesprint.de/blog/magento-statischen-block-ausgeben/ Magento: Statischen Block ausgeben]
  
 +
=== Templates ===
 +
==== aufrufe aus phtml heraus ====
 +
<source lang="php">
 +
<!-- wenn der Block der selbe ist -->
 +
<?php echo $this->setTemplate('path/to/template.phtml')->toHtml(); ?>
 +
 +
<!-- wenn es ein anderer Block ist -->
 +
<?php echo $this->getLayout()->getBlockSingleton('kuerzel_extension/block')->setTemplate('path/to/template.phtml')->toHtml(); ?>
 +
 +
<!-- wenn daten übergeben werden sollen (magische setter methode) -->
 +
<?php echo $this->setTemplate('path/to/template.phtml')->setVariable($value)->toHtml(); ?>
 +
<?php echo $this->getLayout()->getBlockSingleton('kuerzel_extension/block')->setTemplate('path/to/template.phtml')->setVariable($value)->toHtml(); ?>
 +
</source>
 +
 +
'''path/to/template.phtml'''
 +
<source lang="php">
 +
<?php
 +
$value = $this->getVariable();
 +
echo $value;
 +
?>
 +
</source>
  
 +
* links
 +
** http://stackoverflow.com/questions/9019515/setting-model-as-template-data-attribute-for-child-block
 
----
 
----
  
Zeile 105: Zeile 167:
 
  // um in einem template die customer url zu bekommen
 
  // um in einem template die customer url zu bekommen
 
  $customer_url = $this->getUrl('adminhtml/customer/edit/', array('id'=>$val));
 
  $customer_url = $this->getUrl('adminhtml/customer/edit/', array('id'=>$val));
</source>  
+
</source>
 +
 
 +
=== Links ===
 +
* https://gauss-development.com/blog/adding-custom-category-attributes-magento - Kategorie um Attribut erweitern
 +
 
 
== allgemein Frontend ==
 
== allgemein Frontend ==
  
 +
== nicht eingeloggt > registrieren > und wieder zurück zum Ursprung ==
 +
<source lang="php">
 +
if (Mage::getSingleton('customer/session')->isLoggedIn()) {
 +
// der eigentliche code
 +
} else {
 +
Mage::getSingleton('customer/session')->setBeforeAuthUrl(Mage::helper('core/url')->getCurrentUrl());
 +
Mage::app()->getFrontController()->getResponse()->setRedirect( Mage::getUrl('customer/account/create', array('_secure' => true)));
 +
}
 +
</source>
 
=== Links ===
 
=== Links ===
 
* http://www.matthias-zeis.com/archiv/wie-man-menu-mein-benutzerkonto-von-magento-anpasst
 
* http://www.matthias-zeis.com/archiv/wie-man-menu-mein-benutzerkonto-von-magento-anpasst
Zeile 249: Zeile 324:
  
 
= Extension Entwicklung =
 
= Extension Entwicklung =
 +
* [[magento extension: anc_image]] - eine einfache Extension inkl. datenbanktabelle
  
== Name ==
+
== ein neue individuelle Produkt Options Typ ==  
* Entwickler/Firma Kürzel: Anc
+
AncBlancoextension.git
* Modulname: Image
+
branch: anc_blancoextension_eingabetyp
* Komplett: MyImage bzw my_image
+
commit: 7bc7d3901916160385d2588762c49feeb95b5f53
* Extensionpfad: ''/var/www/Magento/AncImage/''
 
* Magento Installation: ''/var/www/Magento/Magento18''
 
  
== xml Konfiguration==
+
== Controller ableiten (rewrite) ==  
=== modul aktivierung ===
+
 
'''/var/www/Magento/AncImage/app/etc/modules/Anc_Image.xml'''
+
AncBlancoextension.git
 +
branch: rewrite_Mage_Checkout_CartController
 +
commit f5c385be1b6bd6c54530c99e0ff6d0aebd5e4353 initial (nur der Controller wurde abgeleitet, noch nichts mit design)
 +
 
 +
'''Beispiel: es soll die /checkout/cart/configure Funktion überschrieben werden!'''
 +
 
 +
neue Extension: <Namespace>/<Module>
 +
 
 +
 
 +
* '''app/etc/modules/<Namespace>_<Module>.xml'''
 
<source lang="xml">
 
<source lang="xml">
 
<?xml version="1.0"?>
 
<?xml version="1.0"?>
 
<config>
 
<config>
    <modules>
+
<modules>
        <Anc_Image>
+
<<Namespace>_<Module>>
            <active>true</active>
+
<active>true</active>
            <codePool>local</codePool>
+
<codePool>local</codePool>
        </Anc_Image>
+
<depends>
    </modules>
+
<Mage_Core />
 +
<Mage_Catalog />
 +
</depends>
 +
</<Namespace>_<Module>>
 +
</modules>
 
</config>
 
</config>
 
</source>
 
</source>
  
=== config.xml - konfiguration der extension ===
+
 
'''/var/www/Magento/AncImage/app/code/etc/config.xml'''
+
* '''app/code/local/<Namespace>/<Module>/etc/config.xml'''
 
<source lang="xml">
 
<source lang="xml">
<?xml version="1.0" encoding="UTF-8"?>
+
<?xml version="1.0"?>
 
<config>
 
<config>
     <!-- versionierung des moduls -->
+
     <modules>
    <modules><Anc_Image><version>0.0.1</version></Anc_Image></modules>
+
        <<Namespace>_<Module>>
     <!-- was im frontend passiert -->
+
            <version>0.1.1</version>
 +
        </<Namespace>_<Module>>
 +
     </modules>
 
     <frontend>
 
     <frontend>
                <!-- einbindung der layoutkonfiguration (s.u.) -->
+
        <routers>
<layout>
+
            <checkout>
<updates>
+
                <args>
<Anc_Image>
+
                    <modules>
<file>anc_image.xml</file>
+
                        <<Namespace>_<Module> before="Mage_Checkout"><Namespace>_<Module></<Namespace>_<Module>>
</Anc_Image>
+
                    </modules>
</updates>
+
                </args>
</layout>
+
            </checkout>
                <!-- damit die controller funktionen über eine url erreichbar sind (s.u.) -->
+
        </routers>
<routers>
+
     </frontend>
<!--Umleitung bzw aktivierung der controllers-->
 
<anc_image>
 
<use>standard</use>
 
<args>
 
<module>Anc_Image</module>
 
<frontName>ancimage</frontName>
 
</args>
 
</anc_image>
 
</routers>
 
     </frontend>
 
    <!-- globale einstellung, derzeit die konfiguration der datenbank schnittstelle -->
 
<global>
 
<models>
 
<anc_image>
 
<class>Anc_Image_Model</class>
 
<!-- folgendes ist ein verweis auf den nachfolgenden tag <anc_image_resource> -->
 
<resourceModel>anc_image_resource</resourceModel>
 
</anc_image>
 
<anc_image_resource>
 
<class>Anc_Image_Model_Resource_Mysql4</class>
 
<!-- entitie's mit s hier können mehrere Tabellen(namen) untergebracht werden -->
 
<entities>
 
<ncimage>
 
<table>anc_image_ncimage</table>
 
</ncimage>
 
</entities>
 
</anc_image_resource>
 
</models>
 
<resources>
 
<!-- hier verbirgt sich das installationsskript um die datenbanktabellen zu erstellen -->
 
<anc_image_setup>
 
<setup>
 
<module>Anc_Image</module>
 
<class>Mage_Sales_Model_Mysql4_Setup</class>
 
</setup>
 
<connection><use>core_setup</use></connection>
 
</anc_image_setup>
 
<!-- datenbank verbindungen -->
 
<anc_image_write><connection><use>core_write</use></connection></anc_image_write>
 
<anc_image_read><connection><use>core_read</use></connection></anc_image_read>
 
</resources>
 
</global>
 
 
</config>
 
</config>
 +
</source>
 +
 +
* '''app/code/local/<Namespace>/<Module>/controllers/CartController.php'''
 +
<source lang="php">
 +
<?php
 +
 +
include_once("Mage/Checkout/controllers/CartController.php"); // wenn hier nicht included wird, gibts ne fehlermeldung
 +
 +
class <Namespace>_<Module>_CartController extends Mage_Checkout_CartController
 +
{
 +
 +
    /**
 +
    * Action to reconfigure cart item
 +
    */
 +
    public function configureAction()
 +
    {
 +
D::li('<Namespace>_<Module>_CartController::configureAction()',1,1); // wäre ne Ausgabe die erscheinen sollte
 +
parent::configureAction();
 +
    }
 +
 +
}
  
 
</source>
 
</source>
  
=== design oberflächen einbindung ===
+
 
anc_image.xml wird über [[#config.xml - konfiguration der extension]] eingebunden
+
 
<source lang="xml">
+
* Links
<frontend><layout><updates><Anc_Image><file>anc_image.xml</file></Anc_Image></updates></layout></frontend>
+
** http://www.fly2mars-media.de/seoblog/magento/magento-core-controller-uberschreiben-101066/
 +
 
 +
== Magento Adminhtml Controller (extends Mage_Adminhtml_Controller_Action) aufrufen über $_Post und $_Get ==
 +
 
 +
=== Get ===
 +
Erzeugt wird eine Url mit Secret Key
 +
$URL = $this->getUrl('image/adminhtml_administrator/uploadImage', array());
 +
 
 +
=== Post===
 +
Erzeugt wird eine Url mit Form Key über die Session
 +
'form_key' = Mage::getSingleton('core/session')->getFormKey();
 +
 
 +
 
 +
== Magento Adminhtml Controller (extends Mage_Adminhtml_Controller_Action) mit jQuery /Dropzone.js aufrufen ==
 +
 
 +
test.phtml
 +
<source lang='javascript' >
 +
<script type="text/javascript">
 +
jQuery(document).ready(function($) {
 +
Anc_Image_Type.droppableFile(
 +
jQuery(" #<?php echo $dropzone_id; ?>"),
 +
null,
 +
"<?php echo $urlUploadImage; ?>",
 +
jQuery(" #<?php echo $ancnote_id; ?>"),
 +
"<?php echo $this->getUrl('image/adminhtml_administrator/simpleowngallery', array()) ?> ul.gallery",
 +
"<?php echo $formkey?>"
 +
);
 +
});
 +
</script>
 
</source>
 
</source>
 +
 +
Über params kann z.B. der form_key für magento übergeben werden
 +
<source lang='javascript' >
 +
param_dropzone_element.dropzone({
 +
url: param_url_upload,
 +
paramName: "file", // The name that will be used to transfer the file
 +
maxFiles: 1,
 +
params: { form_key : param_secure },
 +
processing: function(file) {
 +
...
  
  
  
'''/var/www/Magento/AncImage/app/design/frontend/layout/anc_image.xml'''
 
<source lang="xml">
 
<?xml version="1.0"?>
 
<layout version="0.1.0">
 
    <!-- in "meinem Benutzerkonto" wird  ein weiterer link angezeigt, der über den Controller die neue seite anzeigt -->
 
    <customer_account>
 
        <reference name="customer_account_navigation">
 
            <action method="addLink">
 
<name>owngallery</name>
 
                <path>ancimage/customer/owngallery</path>
 
                <label>Verwalten Sie Ihre Bilder</label>
 
                <urlParams />
 
            </action>
 
        </reference>
 
    </customer_account>
 
  
    <!-- ansicht wird konfiguriert -->
+
</source>
    <anc_image_customer_owngallery>
+
== observer==
<!-- einbindung von javascript und css -->
+
Funktion die die Observer events aufruft
<reference name="head">
+
Mage.php
<action method="addJs"><script>ancimage/dropzone.js</script></action>
+
<source lang="php">
<action method="addCss"><stylesheet>css/ancimage/dropzone.css</stylesheet></action>
+
    public static function dispatchEvent($name, array $data = array())
<action method="addJs"><script>ancimage/jquery.prettyPhoto.js</script></action>
+
    {
<action method="addCss"><stylesheet>css/ancimage/prettyPhoto.css</stylesheet></action>
+
// D::ulli('observer: '.$name);
</reference>
+
        Varien_Profiler::start('DISPATCH EVENT:'.$name);
<!-- einbindung des templates -->
+
        $result = self::app()->dispatchEvent($name, $data);
        <reference name="content">
+
        Varien_Profiler::stop('DISPATCH EVENT:'.$name);
            <block type="core/template" name="anc_image_customer_owngallery" template="ancimage/customer_owngallery.phtml" />
+
        return $result;
        </reference>
+
     }
     </anc_image_customer_owngallery>
 
 
</layout>
 
 
</source>
 
</source>
  
== template ==
+
* https://www.nicksays.co.uk/magento-events-cheat-sheet-1-9/ Liste von alles Events
  
 +
= Create Extension Package =
 +
* [http://www.commercers.com/blog/magento-eigene-erweiterung-erstellen-fur-magento-connect/ Magento – Eigene Erweiterung erstellen für Magento Connect]
  
das template welches in [[Magento_Entwicklung#design_oberflächen_einbindung]] eingebunden wird, wird über den [[Magento_Entwicklung#Controller_-_Schnittstelle_zum_Browser Controller]] Aufruf (über die url) aufgerufen
+
== Authors ==
<source lang="xml">
+
=== invalid or empty login for author #1 ===
    <anc_image_customer_owngallery><reference name="content"><block type="core/template" name="anc_image_customer_owngallery" template="ancimage/customer_owngallery.phtml" /></reference></anc_image_customer_owngallery>
+
admin panel > System > Magento Connect > Paket erstellung
</source>
 
* stellt die Anzeige unserer extension Model/Tabelle 'anc_image/ncimage' dar (aufgewertet durch [http://www.no-margin-for-errors.com/projects/prettyphoto-jquery-lightbox-clone/ prettyPhoto])
 
* beinhaltet ein formular um bilder per drag&drop (dank [http://www.dropzonejs.com/ dropzonejs]) hinzuzufügen.
 
** im formular als action ist wieder ein [[Magento_Entwicklung#Controller_-_Schnittstelle_zum_Browser Controlleraufruf]] enthalten
 
  
 +
* beim speichern kommt immer wieder ''Invalid or empty login for author #1''
  
 +
im Reiter "Authors" muss der Benutzername der NAchname vom [https://www.magentocommerce.com/ magentocommerce]  sein!!!!!
  
'''/var/www/Magento/AncImage/app/design/frontend/template/ancimage/customer_owngallery.phtml'''
 
<source lang="php">
 
  
<?php if(Mage::getSingleton('customer/session')->isLoggedIn()): ?>
+
== Dependencies ==
<?php $customer = Mage::getSingleton('customer/session')->getCustomer(); ?>
+
===  PHP minimum version invalid===
  
<!-- Anzeige der Daten -->
+
mit 2 punkten ...
 +
'''5.4.0'''
  
<?php $ncimages = Mage::getModel('anc_image/ncimage')->getCollection()->addFieldToFilter('ancii_customer_id', $customer->getId());  ?>
 
<?php $path = DS.'media'.DS.'anc'.DS.'image'.DS.'customer'.DS.$customer->getId().DS; ?>
 
  
<ul class="gallery clearfix">
+
== Inhalte ==
<?php foreach($ncimages->getItems() as $ncimage ): ?>
+
Wichtig: die Pfade fangen immer erst im jeweiligen Unterordner an,
<a rel="prettyPhoto[pp_gal2]" href="<?php echo $path.$ncimage['ancii_file'] ?>" title="You can add caption to pictures.">
+
  zB app/code/community darf nicht im Pfad enthalten sein wenn Magento Community module ausgewählt wurde,
<img height="50" src="<?php echo $path.$ncimage['ancii_file'] ?>" >
+
  es gibt keine Fehlermeldung, Dateien werden aber auch nicht hinzugefügt
</a>
 
<?php endforeach; ?>
 
</ul>
 
 
<script type="text/javascript">
 
 
jQuery(document).ready(function($) {
 
jQuery("a[rel^='prettyPhoto']").prettyPhoto({});
 
});
 
</script>
 
 
<!-- Formular eingabe der Daten -->
 
<form action="<?php echo $this->getUrl('ancimage/customer/uploadImage'); ?>" class="dropzone">
 
<div class="fallback"><input name="file" type="file" multiple /></div>
 
</form>
 
<?php else: ?>
 
<h1>Bitte loggen Sie sich ein!</h1>
 
<?php endif; ?>
 
  
</source>
 
  
== app code - die eigentliche code logik inklusive datenbank zugriff ==
+
*  '''Magento Community module''' file dies bezieht sich auf den Ordner app/code/community
=== Controller - Schnittstelle zum Browser ===
+
** Anc/Pricespercustomer/
 +
*** Rekursiv Verzeichnis
  
'''/var/www/Magento/AncImage/app/code/controllers/CustomerController.php'''
+
'''Magento User Interface (layouts, templates)''' dies bezieht sich auf den Ordner app/design
<source lang="php">
+
** adminhtml/default/default/layout/anc/pricespercustomer.xml
<?php
+
*** Datei
/**  
+
** adminhtml/default/default/template/anc/pricespercustomer/
* Controller ist dank @see app/code/etc/config.xml im <routers> tag
+
*** Rekursiv Verzeichnis
* als url direkt im Browser erreichbar
 
*/
 
class Anc_Image_CustomerController extends Mage_Core_Controller_Front_Action {
 
    protected function _initAction() {
 
$this->loadLayout();
 
return $this;
 
    }
 
/**
 
* fnc ist in "mein Benutzerkonto" laut @see @see app/design/frontend/layout/anc_image.xml als link aufrufbar,
 
* * durch selbige anc_image.xml bekommt die fnc das template @see app/design/frontend/template/ancimage/customer_owngallery.phtml beigesteuert
 
*/
 
public function owngalleryAction() {
 
$this->loadLayout();
 
$this->getLayout()->getBlock('root')->setTemplate('page/1column.phtml');
 
$this->renderLayout();
 
}
 
 
/**
 
* fnc wird übers formular von owngalleryAction() bzw customer_owngallery.phtml
 
* bei einem datei upload aufgerufen und verarbeitet die post werte
 
* * kopiert datei in entsprechendes kunden verzeichniss
 
* * speichert dateiname im model / in tabelle
 
*/
 
public function uploadImageAction() {
 
 
if (Mage::getSingleton('customer/session')->isLoggedIn()) {
 
  
/* Get the customer data */
+
*  '''Magento Global Configuration''' dies bezieht sich auf den Ordner app/etc
$customer = Mage::getSingleton('customer/session')->getCustomer();
+
** modules/Anc_Pricespercustomer.xml
+
*** Datei
if(isset($_FILES['file']['name']) && $_FILES['file']['name'] != '') {
 
try
 
{     
 
$path = Mage::getBaseDir().DS.'media'.DS.'anc'.DS.'image'.DS.'customer'.DS.$customer->getId().DS; //desitnation directory   
 
$fname = $_FILES['file']['name']; //file name                     
 
$uploader = new Varien_File_Uploader('file'); //load class
 
$uploader->setAllowedExtensions(array('jpg','jpeg','gif','png')); //Allowed extension for file
 
$uploader->setAllowCreateFolders(true); //for creating the directory if not exists
 
$uploader->setAllowRenameFiles(false); //if true, uploaded file's name will be changed, if file with the same name already exists directory.
 
$uploader->setFilesDispersion(false);
 
$uploader->save($path,$fname); //save the file on the specified path
 
  
$ncimage = Mage::getModel('anc_image/ncimage');
+
'''Magento Locale language file''' dies bezieht sich auf den Ordner app/locale
$ncimage->setData('ancii_customer_id',$customer->getId());
+
** de_DE/anc/pricepercustomer.csv
$ncimage->setData('ancii_path', $path);
+
*** Datei
$ncimage->setData('ancii_file',$fname);
 
$ncimage->save();
 
 
} catch (Exception $e) {
 
echo 'Error Message: !! '.$e->getMessage();
 
}
 
}
 
  
} else {
+
= nützliche Entwickler Extensions =
echo('nicht eingeloggt');
+
== Layout: unremove ==
}
+
so was wie
}
+
<source lang="xml">
}
+
<remove name="right"/>
 
</source>
 
</source>
=== die datenbankverbindung ===
+
rückgängig machen
  
== Verlinkungen ==
+
ganz einfach mit
<source lang="bash">
 
  
ln -s /var/www/Magento/MyImage/app/code  /var/www/Magento/Magento18/app/code/local/My/Image
+
<source lang="xml">
ln -s /var/www/Magento/MyImage/app/etc/modules/My_Image.xml  /var/www/Magento/Magento18/app/etc/modules/My_Image.xml
+
<x-unremove name="right" />
 +
</source>
 +
* http://alanstorm.com/magento_layout_unremove_in_local_xml
 +
** http://www.magentocommerce.com/magento-connect/layout-unremove.html
 +
** http://connect20.magentocommerce.com/community/Layout_Unremove
  
#
+
= Fehler =
# folgende Verknüpfung fürs Design muss noch gemacht werden
+
== var/log/exception.log: exception 'Mage_Core_Exception' with message 'Ungültiger Blocktyp: Mage_***_***_Block_Adminhtml_Catalog_Product_Edit_Tab_Options_Type_***' in ../app/Mage.php:595 ==
#
 
  
# wenn base/default genommen wird, wird die extension (bzw in diesem fall das layout) in jedem design eingebunden
+
mögliche Probleme:
ln -s /var/www/Magento/MyImage/app/design/frontend/layout/my_image.xml /var/www/Magento/Magento18/app/design/frontend/base/default/layout/my_image.xml
 
ln -s /var/www/Magento/MyImage/app/design/frontend/template/ancimage/ /var/www/Magento/Magento18/app/design/frontend/base/default/template/myimage
 
 
# folgendes führt dazu das die extension ausschließlich im default/default design eingebunden wird
 
ln -s /var/www/Magento/MyImage/app/design/frontend/layout/my_image.xml /var/www/Magento/Magento18/app/design/frontend/default/default/layout/my_image.xml
 
ln -s /var/www/Magento/MyImage/app/design/frontend/template/ancimage/ /var/www/Magento/Magento18/app/design/frontend/default/default/template/myimage
 
  
 +
* fehlende Layout Konfiguration
 +
** app/code/local/Anc/Site/etc/config.xml
 +
<source lang="xml">
 +
<config>
 +
<global>
 +
<blocks>
 +
<anc_site>
 +
<class>Anc_Site_Block</class>
 +
</anc_site>
 +
</blocks>
 +
</global>
 +
</config>
 
</source>
 
</source>
 
== Quellen ==
 
* [http://www.matthias-zeis.com/archiv/magento-eigene-extension-erstellen#Was-brauche-ich-fr-eine-eigene-Extension Magento: eigene Extension erstellen]
 

Aktuelle Version vom 13. Dezember 2016, 14:42 Uhr

magento extension: anc_image - eine einfache Extension inkl. datenbanktabelle

Entwicklung

globale Funktionsaufrufe

Cache Löschen

Mage::app()->cleanCache();

eingeloggt

if(Mage::getSingleton('customer/session')->isLoggedIn()) {
	$customer_id = Mage::getSingleton('customer/session')->getCustomer()->getId(); 

} else if(Mage::app()->getStore()->isAdmin()) {
	$admin_id = Mage::getSingleton('admin/session')->getUser()->getId();
}

anderes

dieses sind allgemeine Funktionsaufrufe, die nahe zu überall (oder Kontex bezogen) aufgerufen werden können

/**
 * hole _POST und _GET Variablen
 */
$post_get_array = Mage::app()->getRequest();


/**
 * aktuelle url
 */
Mage::helper('core/url')->getCurrentUrl();

Session

/**
 * hole aktuelle Session
 */
$session = Mage::getSingleton('checkout/session');

// was in die session schreiben mit den magischen Funktionen
Mage::getSingleton('checkout/session')->setName('Value');
Mage::getSingleton('checkout/session')->set<Variablenname>('Value');

// was aus der session holen mit den magischen Funktionen
Mage::getSingleton('checkout/session')->getName('Value');
Mage::getSingleton('checkout/session')->get<Variablenname>('Value');

Model

/** 
 * product laden - achtung er lädt wirklich jedes mal neu, auf jeden fall chachen
 */
$product = Mage::getModel("catalog/product");
$product = $product->load($param_id);
$product_data = $product->getData();

// ein model laden, welches nicht über id identifiziert wird, sprich andere tabellenspalte (Achtung, auch wenn mehrere ergibt nur eins zurück )
$ncimages = Mage::getModel('kürzel_modulename/modeltabelleklasse')->load($value, 'tabellenspaltenname');

// zeige max() eines query
$quote = Mage::getSingleton('checkout/session')->getQuote();
$collection = Mage::getModel('sales/quote_item')->getCollection();
$string_sql = $collection->getSelect()->reset(Zend_Db_Select::COLUMNS)->columns('max(item_id) as last_item_id')
				    ->where("quote_id = ".$quote->getId()); 
$lastItemId = $collection->getData();

D::s($collection->getData(), '$maxItemId: '.$lastItemId[0]['last_item_id']);

Frontend: Warenkorb

/**
 * hole aktuellen Quote (Angebot)
 */
$quote = Mage::getSingleton('checkout/session')->getQuote();

            // Mage::registry('product');
            if (Mage::registry('current_product')) {
                $this->_product = Mage::registry('current_product');
            } else {
                $this->_product = Mage::getSingleton('catalog/product');
            }


/**
 * wenn mensch ein Posten im Warenkorb bearbeitet, kann sich über die Url=/checkout/cart/configure/id/751/ (_GET) die aktuelle Item ID geholt werden
 */
$getParamId = Mage::app()->getRequest()->getParam('id')

backend

// ist mensch admin
Mage::app()->getStore()->isAdmin();
$admin_id = Mage::getSingleton('admin/session')->getUser()->getId();


Backend Tables (Grid)

Beispiel für Backend Grids

Block .... schnipsel

{{block type=”catalog/product_list” category_id=”[Ihre Kategorie ID]” template=”catalog/product/list.phtml”}}

Statische Blöcke

Admin Panel >> CMS > Statische Blöcke >> Neuer Block
  • interner Bezeichner: wichtig_dieser_wird_benutzt_um_im_Code_drauf_zuzugreifen
  • Status: aktiviert
  • der rest nach Belieben
<?php echo $this->getLayout()->createBlock('cms/block')->setBlockId('wichtig_dieser_wird_benutzt_um_im_Code_drauf_zuzugreifen')->toHTML(); ?>

<!-- es kann natürlich auch die ID genommen werden, ist aber wohl ja eher unpraktisch -->
<?php echo $this->getLayout()->createBlock('cms/block')->setBlockId('10')->toHTML(); ?>

Quelle


Templates

aufrufe aus phtml heraus

<!-- wenn der Block der selbe ist -->
<?php echo $this->setTemplate('path/to/template.phtml')->toHtml(); ?>

<!-- wenn es ein anderer Block ist -->
<?php echo $this->getLayout()->getBlockSingleton('kuerzel_extension/block')->setTemplate('path/to/template.phtml')->toHtml(); ?>

<!-- wenn daten übergeben werden sollen (magische setter methode) -->
<?php echo $this->setTemplate('path/to/template.phtml')->setVariable($value)->toHtml(); ?>
<?php echo $this->getLayout()->getBlockSingleton('kuerzel_extension/block')->setTemplate('path/to/template.phtml')->setVariable($value)->toHtml(); ?>

path/to/template.phtml

<?php
$value = $this->getVariable();
echo $value;
?>

allgemein Backendend

 // um in einem template die customer url zu bekommen
 $customer_url = $this->getUrl('adminhtml/customer/edit/', array('id'=>$val));

Links

allgemein Frontend

nicht eingeloggt > registrieren > und wieder zurück zum Ursprung

if (Mage::getSingleton('customer/session')->isLoggedIn()) {
	// der eigentliche code
} else {
	Mage::getSingleton('customer/session')->setBeforeAuthUrl(Mage::helper('core/url')->getCurrentUrl());
	Mage::app()->getFrontController()->getResponse()->setRedirect( Mage::getUrl('customer/account/create', array('_secure' => true)));
}

Links


jquery

local.xml

<block type="page/html_head" name="head" as="head">
  ...
 <action method="addJs"><script>scripts/jquery-1.6.min.js</script></action>
 <action method="addJs"><script>scripts/blogrammierer.js</script></action>
</block>

scripts/blogrammierer.js

$.noConflict();
jQuery(document).ready(function($) {     
  // Hier der eigentliche Jquery-Quellcode
});


Unterkategorien einer Kategorie inklusive Bilder und Beschreibung anzeigen

1. Statischen Block anlegen (Backend > CMS > Statische Blöcke >> Neuer Block)

  • Blocktitel: subcategory_listing_full
  • Interner Bezeichner: subcategory_listing_full
  • Status: Aktiviert
  • Inhalt (WYSIWYG Editor ausschalten): eine der folgenden Aufrufe eingen
 <!-- nur typo und template: er nimmt die Kategorie die (per url) aufgerufen wird -->
 {{block type="catalog/navigation"template="catalog/navigation/subcategory_listing_full.phtml"}}
 <!-- parameter category_id: er nimmt die Kategorie Id als Grundlage und ignoriert die Url -->
 {{block type="catalog/navigation" category_id="8" template="catalog/navigation/subcategory_listing_full.phtml"}}
 <!-- zusätzlich falls nur der Name ohne Bilder und Beschreibung angezeigt werden soll -->
 {{block type="catalog/navigation" category_id="8" only_name="1" template="catalog/navigation/subcategory_listing_full.phtml"}}

2. folgende Datei anlegen

app/design/frontend/<<OWNDESIGN>>/default/template/catalog/navigation/subcategory_listing_full.phtml

<div id="categories" class="listing">
	<?php
	
		$_maincategorylisting = $this->getCurrentCategory();
		$layer = Mage::getSingleton('catalog/layer');
		
		/**
		 *  category_id="X" im Blockaufruf angegeben wurde, dann nimm diese Kategorie als Grundlage
		 *	{{block type="catalog/navigation" category_id="8" template="catalog/navigation/subcategory_listing_full.phtml"}}
		 */
		if($this->getCategoryId()) {
			$paramCategory = Mage::getModel('catalog/category')->load($this->getCategoryId());
			$this->setCurrentCategory($paramCategory);		
			$layer->setCurrentCategory($paramCategory);
		}
		$_categories = $this->getCurrentChildCategories();
		$_helper = $this->helper('catalog/output'); 
	?>
	<?php if(count($_categories)):?>
		<?php foreach ($_categories as $_category):?>
			<?php if($_category->getIsActive()): ?>
				<?php
					$cur_category=Mage::getModel('catalog/category')->load($_category->getId());	
					$layer->setCurrentCategory($cur_category);
					$catName = $this->getCurrentCategory()->getName(); 
				?>
				<?php if(!$this->getOnlyName() && $_imageUrl=$this->getCurrentCategory()->getImageUrl()):?>
					<div class="category-image"><a href="<?php echo $this->getCategoryUrl($_category)?>"><img src="<?php echo $_imageUrl?>" height="188"></a></div>
				<?php endif;?>
				<div class="category-name"><a href="<?php echo $this->getCategoryUrl($_category)?>"> <?php echo $_category->getName()?></a></div>
				<?php if(!$this->getOnlyName() && $_description=$this->getCurrentCategory()->getDescription()): ?>
					<div class="category-description"><?php echo $_helper->categoryAttribute($_category, $_description, 'description') ?></div>
				<?php endif; ?>					
			<?php endif; ?>
		<?php endforeach?>
		<?php
			if($this->getCategoryId()) {
				$this->setCurrentCategory($_maincategorylisting);
			}
			$layer->setCurrentCategory($_maincategorylisting);  
		?> 
	<?php endif;?>
</div>

3. statischen Block einbinden

  • zb
    • über CMS > Seiten
    • oder CMS > Statische Blöcke >> Footer Links
    • oder über eine spezielle Kategorie Katalog > Kategorien verwalten >> spezielle Kategorie > Anzeige Einstellungen >> CMS Block

Quellen

interessante Links

Blog-Hints aktivieren

Admin > System > Konfiguration > Entwickleroptionen > obenlinks "Aktueller Konfig.-Bereich" > Main Website
  • Debug
    • Vorlagen Pfadhinweise: Ja
    • Blocknamen zu Hinweisen hinzufügen: Ja


Magento-Themes einfacher erstellen und modifizieren

cd Magento18/
cp -r app/design/frontend/base/default   app/design/frontend/default/my_theme
cd  app/design/frontend/default/my_theme
find -type f -exec rename -n 's/$/-disabled/' '{}' ';'     # simulation
find -type f -exec rename  's/$/-disabled/' '{}' ';'

cd ../../../../../../Magento18/
cp -r skin/frontend/base/default/ skin/frontend/default/my_theme/
cd skin/frontend/default/my_theme/
find -type f -exec rename -n 's/$/-disabled/' '{}' ';'     # simulation
find -type f -exec rename  's/$/-disabled/' '{}' ';'

cp app/design/frontend/default/my_theme/template/catalog/product/view.phtml-disabled app/design/frontend/default/my_theme/template/catalog/product/view.phtml





Extension Entwicklung

ein neue individuelle Produkt Options Typ

AncBlancoextension.git
branch: anc_blancoextension_eingabetyp
commit: 7bc7d3901916160385d2588762c49feeb95b5f53

Controller ableiten (rewrite)

AncBlancoextension.git 
branch: rewrite_Mage_Checkout_CartController 
commit f5c385be1b6bd6c54530c99e0ff6d0aebd5e4353 initial (nur der Controller wurde abgeleitet, noch nichts mit design)

Beispiel: es soll die /checkout/cart/configure Funktion überschrieben werden!

neue Extension: <Namespace>/<Module>


  • app/etc/modules/<Namespace>_<Module>.xml
<?xml version="1.0"?>
<config>
	<modules>
		<<Namespace>_<Module>>
			<active>true</active>
			<codePool>local</codePool>
			<depends>
				<Mage_Core />
				<Mage_Catalog />
			</depends>				
		</<Namespace>_<Module>>
	</modules>
</config>


  • app/code/local/<Namespace>/<Module>/etc/config.xml
<?xml version="1.0"?>
<config>
    <modules>
        <<Namespace>_<Module>>
            <version>0.1.1</version>
        </<Namespace>_<Module>>
    </modules>
    <frontend>
        <routers>
            <checkout>
                <args>
                    <modules>
                         <<Namespace>_<Module> before="Mage_Checkout"><Namespace>_<Module></<Namespace>_<Module>>
                    </modules>
                </args>
            </checkout>	
        </routers>	
    </frontend>
</config>
  • app/code/local/<Namespace>/<Module>/controllers/CartController.php
<?php

include_once("Mage/Checkout/controllers/CartController.php"); // wenn hier nicht included wird, gibts ne fehlermeldung

class <Namespace>_<Module>_CartController extends Mage_Checkout_CartController
{
 
    /**
     * Action to reconfigure cart item
     */
    public function configureAction()
    {
		D::li('<Namespace>_<Module>_CartController::configureAction()',1,1); // wäre ne Ausgabe die erscheinen sollte
		parent::configureAction();
    }

}


Magento Adminhtml Controller (extends Mage_Adminhtml_Controller_Action) aufrufen über $_Post und $_Get

Get

Erzeugt wird eine Url mit Secret Key

$URL = $this->getUrl('image/adminhtml_administrator/uploadImage', array());

Post

Erzeugt wird eine Url mit Form Key über die Session

'form_key' = Mage::getSingleton('core/session')->getFormKey();


Magento Adminhtml Controller (extends Mage_Adminhtml_Controller_Action) mit jQuery /Dropzone.js aufrufen

test.phtml

 <script type="text/javascript">
						jQuery(document).ready(function($) {
							Anc_Image_Type.droppableFile(
								jQuery(" #<?php echo $dropzone_id; ?>"), 
								null, 
								"<?php echo $urlUploadImage; ?>",
								jQuery(" #<?php echo $ancnote_id; ?>"), 
								"<?php echo $this->getUrl('image/adminhtml_administrator/simpleowngallery', array()) ?>  ul.gallery",
								"<?php echo $formkey?>"
							);
						}); 
 </script>

Über params kann z.B. der form_key für magento übergeben werden

			param_dropzone_element.dropzone({ 
				url: param_url_upload,
				paramName: "file", // The name that will be used to transfer the file
				maxFiles: 1, 
				params: { form_key : param_secure },
				processing: function(file) { 
				...

observer

Funktion die die Observer events aufruft Mage.php

    public static function dispatchEvent($name, array $data = array())
    {
// D::ulli('observer: '.$name);
        Varien_Profiler::start('DISPATCH EVENT:'.$name);
        $result = self::app()->dispatchEvent($name, $data);
        Varien_Profiler::stop('DISPATCH EVENT:'.$name);
        return $result;
    }

Create Extension Package

Authors

invalid or empty login for author #1

admin panel > System > Magento Connect > Paket erstellung
  • beim speichern kommt immer wieder Invalid or empty login for author #1

im Reiter "Authors" muss der Benutzername der NAchname vom magentocommerce sein!!!!!


Dependencies

PHP minimum version invalid

mit 2 punkten ... 5.4.0


Inhalte

Wichtig: die Pfade fangen immer erst im jeweiligen Unterordner an, 
 zB app/code/community darf nicht im Pfad enthalten sein wenn Magento Community module ausgewählt wurde, 
 es gibt keine Fehlermeldung, Dateien werden aber auch nicht hinzugefügt


  • Magento Community module file dies bezieht sich auf den Ordner app/code/community
    • Anc/Pricespercustomer/
      • Rekursiv Verzeichnis
  • Magento User Interface (layouts, templates) dies bezieht sich auf den Ordner app/design
    • adminhtml/default/default/layout/anc/pricespercustomer.xml
      • Datei
    • adminhtml/default/default/template/anc/pricespercustomer/
      • Rekursiv Verzeichnis
  • Magento Global Configuration dies bezieht sich auf den Ordner app/etc
    • modules/Anc_Pricespercustomer.xml
      • Datei
  • Magento Locale language file dies bezieht sich auf den Ordner app/locale
    • de_DE/anc/pricepercustomer.csv
      • Datei

nützliche Entwickler Extensions

Layout: unremove

so was wie

<remove name="right"/>

rückgängig machen

ganz einfach mit

<x-unremove name="right" />

Fehler

var/log/exception.log: exception 'Mage_Core_Exception' with message 'Ungültiger Blocktyp: Mage_***_***_Block_Adminhtml_Catalog_Product_Edit_Tab_Options_Type_***' in ../app/Mage.php:595

mögliche Probleme:

  • fehlende Layout Konfiguration
    • app/code/local/Anc/Site/etc/config.xml
<config>
	<global>
		<blocks>
			<anc_site>
				<class>Anc_Site_Block</class>
			</anc_site>
		</blocks>
	</global>
</config>