Models in Zend Framework - javascript

I am new to zend framework. I have created "models" folder in application directory. Inside models folder I created a class Application_Models_Albums which extends Zend_Db_Table_Abstract.
Now when I use the following code in IndexController. I get error:
$albums = new Application_Models_Albums();
$this->view->albums = $albums->fetchAll();
Error: Fatal error: Class 'Application_Models_Albums' not found in
H:\Documents\IIS Server
Root\localhost\learning\zf1\application\controllers\IndexController.php
on line 13
Please help. How can I load models in zend framework?

You need to name your model Albums. and save in models/albums.php
The auto-loader will figure out where to load it from by the name. so even though the model is named albums, you call it by new Application_Models_Albums()
The autoloader find it in application/models/albums.php
similarly the Zend_Db_Table_Abstract class is located in Zend/Db/Table/Abstract.php
edit
IF you cant get the autoloader to work, you can do it the quick and easy way by just adding models/ to your include path. I've done this before and it works fine.
Something like set_include_path(get_include_path().PATH_SEPERATOR."models/") in your index.php

Your model class name should be Application_Model_Albums - with Model in singular.
See http://framework.zend.com/manual/en/zend.loader.autoloader-resource.html for more info on Zend Autoloader.

you need to require your model class-
require_once 'PathToModel\Application_Models_Albums.php';
some people create autoloader classes to deal with this, YMMV

It sounds like your Bootstrap or application.ini needs to specify the namespace as 'Application_'.
In Bootstrap.php:
protected function _initAutoloader()
{
$autoloader = new Zend_Application_Module_Autoloader(array(
'basePath' => APPLICATION_PATH,
'namespace' => 'Kwis_',
));
return $autoloader;
}
Alernatively, in configs/application.ini:
appnamespace = "Application_"

You could also extend Zend_Controller_Action and add a method like this:
protected $_tables = array();
protected function _getTable($table)
{
if (false === array_key_exists($table, $this->_tables)) {
require_once(APPLICATION_PATH.'/modules/'.$this->_request->getModuleName().'/models/'.$table.'.php');
$this->_tables[$table] = new $table();
}
return $this->_tables[$table];
}

Related

Why is a function provided by require undefined in a class instance? [duplicate]

This question already has an answer here:
Require returns an empty object
(1 answer)
Closed 1 year ago.
I'm asking this mostly as a sanity check, I'm unsure if I have made a mistake somewhere or if this fundamentally does not work.
I am converting some Java to Nodejs, A class called Site populates itself from a database via the dataFunctions.getSiteInfo(id) function. It also stores a list of Page instances.
The issue is that dataFunctions is returning as undefined when an instance of Site is created.
Have I misunderstood how classes and modules work in this case? Is it possible for instances of this class to access the dataFunctions module? Likewise is it possible for the Site class to reference the Page class as well? Or have I made some other silly mistake?
Site.js
let Page = require('./Page.js');
let dataFunctions = require('../DataFunctions.js');
module.exports = class Site {
constructor(id) {
this.id = id;
this.pages = [];
console.log(dataFunctions);
this.siteInfo = dataFunctions.getSiteInfo(id);
DataFunctions.js
let Site = require('./classes/Site.js');
function makeASite() {
let id = 2;
let site = new Site(id);
}
function getSiteInfo(id) {
etc etc
}
module.exports = {
getSiteInfo: function (id) {
return getSiteInfo(id);
},
};
Based on the code provided, I believe you forgot to create a new dataFunctions instance.
const df = new dataFunctions();
console.log(df);
If dataFunctions is providing static functions, make sure that the getSiteInfo method is static.
Otherwise, additional details may be needed.
Edit
It looked like the project structure and the require paths were wonky, but it's hard to tell.
When I run the code provided using the project structure inferred by the require statements, I'm not able to reproduce your issue.
However, one problem that I do see is that you're requiring the Site.js module from the DataFunctions.js module and requiring the DataFunctions.js module from the Site.js module, creating circular dependencies. Try eliminating these by moving makeASite to the Site.js module, for instance.

Symfony & Sonata : How to add javascript to entity admin form?

New to Symfony & Sonata I created an entity "Foo" with the associated App\Admin class :
<?php
namespace App\Admin;
final class FooAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('Zorg', ['class' => 'col-md-4'])
->add('name', TextType::class)
->end();
}
...
}
Everything works fine.
I can access the list, add and edit Foo.
I now would like to add a javascript script in the add and edit forms.
How can I do that? May I have to use assets and Encore?
Is there another/best way?
Thank you for your help
If you are using Encore then below should work:
# config/packages/sonata_admin.yaml
sonata_admin:
assets:
extra_stylesheets:
- build/app.css
extra_javascripts:
- build/runtime.js
- build/app.js

How to expose JS patch function of Incremental DOM library in GWT app using #JsInterop

I would like to use Incremental DOM library in my GWT app.
https://google.github.io/incremental-dom/#about
As I am coming from the Java world, I struggle with concepts of JavaScript namespaces and modules. I was able to use Closure Compiler with closure version of Incremental DOM (has to be build from sources).
It starts with the following line:
goog.module('incrementaldom');
So if I was to use it in regular JS I would type:
var patch = goog.require('incrementaldom').patch;
And then the patch function would be available in the scope of my code. But how to make it accessible from #JsInterop annotated classes?
I tried something like:
public class IncrementalDom {
#JsMethod(namespace = "incrementaldom", name = "patch")
public static native void patch(Element element, Patcher patcher);
#JsFunction
#FunctionalInterface
public interface Patcher {
void apply();
}
}
But it doesn't work. I get this error in the runtime:
(TypeError) : Cannot read property 'patch' of undefined
So I guess I have to somehow expose the incrementaldom module or at least only the patch method. But I don't know how.
After fighting for the whole day I found the solution. In the goog.module: an ES6 module like alternative to goog.provide document I found the missing information about the role of goog.scope function - required modules are visible only within the scoped call.
I created another Closure JS file named incrementaldom.js:
goog.provide('app.incrementaldom'); // assures creation of namespace
goog.require("incrementaldom");
goog.scope(function() {
var module = goog.module.get("incrementaldom");
var ns = app.incrementaldom;
app.incrementaldom.patch = module.patch;
});
goog.exportSymbol("app.incrementaldom", app.incrementaldom);
And now I can call it from Java code like this:
public class IncrementalDom {
#JsMethod(namespace = "app.incrementaldom", name = "patch")
public static native void patch(Element element, Patcher patcher);
#JsFunction
#FunctionalInterface
public interface Patcher {
void apply();
}
}
Still I have to define every object exported in original module separately in the Closure JS file. Fortunately I only need patch method. I hope one day I will find less cumbersome way for #JsInterop with goog.module :(

Where to Include Sugarcrm

I have been working on some custom code for a sugar module and am fairly unclear where to put my javascript code to be called in module.
Currently I have put my custom JS in include/javascript/popup_parent_helper.js
This works fine in developer mode but does not work when that is turned off and unfortunately dveloper mode runs SUPER slow
I have done a lot of research and I am getting some conflicting results.
Some tell me that I should include it in:
/modules/[ModuleName]/
Others say that it should to in:
/custom/modules/[ModuleName/
and some further in adding js as a directory
Please help me clarify proper structure for this and where I need to make my proper include statement
Clarifications:
We are using SugarCrm 6.5x
In this case the JS is only being used for one module.
It is being used in the Quick Create View and the Edit View
If the javascript should be accessible by any module, you can create a new JSGrouping and pull in your custom js file using the following technique:
http://support.sugarcrm.com/Documentation/Sugar_Developer/Sugar_Developer_Guide_7.6/Extension_Framework/JSGroupings/#Creating_New_JSGroupings
It sounds like you want it to be isolated to your custom module, so you should probably extend the view desired. If you are extending the record view, create a new file called record.js at custom/modules/-your_module-/clients/base/views/record/
({
extendsFrom: 'RecordView',
initialize: function(options) {
this._super('initialize', [options]);
this.doSomething();
},
doSomething: function(){
console.log("Help you I will");
},
...
})
https://developer.sugarcrm.com/2014/02/10/extending-sugar-7-record-view/
I had also faced similar issue (JS should be work for edit and quickcreate form) but after making some RnD I achieved it as per following way:
\custom\modules\<modulename>\views\view.edit.php
<?php
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
require_once('include/MVC/View/views/view.edit.php');
class {moduleName}ViewEdit extends ViewEdit {
public function __construct() {
parent::ViewEdit();
$this->useForSubpanel = true; // this variable specifies that these changes should work for subpanel
// / $this->useModuleQuickCreateTemplate = true; // quick create template too
}
function display(){ ?>
<?php
$jsscript = <<<EOQ
<script>
Your JS code
</script>
EOQ;
parent::display();
echo $jsscript; //echo the script
}
}
?>

updating javascript in the body tag using zend framework

Hi not sure if this is possible or not but I want to programaticaly update the <body> tags to change the onload function in my zend framework application.
The App is using layouts so the body tag currently looks like this <body class="trandra">
However in one of my views I have a map from google being loaded and it needs the following in the body tag this particular view <body onload="initialize()" onunload="GUnload()">
As you can understand I don't want this to be hardcoded in my layout as this will cause all matter of nightmares with the different views.
How can this be done programaticaly, if at all it is possible? Im using the headScript functions to add the javascript so is there an equivalant for the body tag?
Thanks in advance...
Approach one - Use a layout variable
One idea would be the following:
<body class="trandra" <?php echo $this->layout()->bodyScripts ?>>
And in your view:
<?php
$this->layout->bodyScripts =
'onload="initialize()" onunload="GUnload()"';
Approach two - Additional JS-file that adds event handlers
Another approach, which is less obtrusive and doesn't affect the HTML whatsoever is to add an additional JS-file in the view that requires the onload- and onunload-handlers. It could look something like this:
<?php
$this->headScript()->appendScript(
'/path/to/javascripts/loadGMaps.js');
In your loadGMaps.js (using prototype)
Event.observe(window, 'load', function onLoadHandler() {
// Code for initializing Google maps here
});
Event.observe(window, 'unload', function onUnloadHandler() {
// Code for unloading Google maps here
});
Instead of putting your Javascript directly in the code, you could also use an non-obstrusive approch : plugging in the javascript when the page is fully loaded.
Have a look, for instance, at a function called addOnLoadEvent (can be found on many websites ^^ )
If you are using a JS Framework, it certainly has that kind of feature :
for jQuery : http://docs.jquery.com/Events/ready#fn
for prototype : http://www.prototypejs.org/api/event/observe
If you register the "plugging-in" with headScript, there should be no need to modify the tag directly.
Developed something like this recently, I've blogged about it here: http://www.evilprofessor.co.uk/311-zend-framework-body-tag-view-helper/
Demo on site and code is available via github.
I'm no expert on the Zend framework, so I don't know if there is any build in functions for this, but you could do something like this:
In layout-file:
body_params?>>
And then in your controller, you set or add to the body_params:
$this->view->body_params='onload="initialize()" onunload="GUnload()"';
I know this is an old thread, but I was looking through some of the suggested solutions and came up with one of my own playing off of some of the ideas I had seen. What I did was I extended Zend_View in my own library files (I'm using a vanilla MVC layout but similar things can be done using a bootstrap.php rather than the Bootstrap class described below)
class Custom_View extends Zend_View
{
protected $bodyAttrs = array();
public function _setBodyAttr($attrName,$attrValue=null) {
$attrName = strtolower(strval($attrName));
if(!(in_array($attrName, HTML::getValidBodyAttrs()))) {
throw new Zend_Exception(__METHOD__." attrName '$attrName' is not a valid BODY attribute!");
}
$this->bodyAttrs[$attrName] = strval($attrValue);
}
public function _getBodyAttrsAsString() {
$bodyAttrs = "";
if(count($this->bodyAttrs) > 0) {
$attrs = array();
foreach($this->bodyAttrs as $_k => $_v) {
array_push($attrs,sprintf("%s=\"%s\"", $_k, $_v));
}
$bodyAttrs = " " . implode(" ", $tags);
}
return $bodyAttrs;
}
}
// some useful tag definitions for HTML
class HTML
{
// HTML attributes as described by W3C
public static $BODY_ATTRIBUTES = array('alink','background','bgcolor','link','text','vlink');
public static $GLOBAL_ATTRIBUTES = array('accesskey','class','contenteditable','contextmenu','dir','draggable','dropzone','hidden','id','lang','spellcheck','style','tabindex','title');
public static $WINDOW_EVENT_ATTRIBUTES = array('onafterprint','onbeforeprint','onbeforeunload','onerror','onhaschange','onload','onmessage','onoffline','ononline','onpagehide','onpageshow','onpopstate','onredo','onresize','onstorage','onundo','onunload');
public static $MOUSE_EVENT_ATTRIBUTES = array('onclick','ondblclick','ondrag','ondragend','ondragenter','ondragleave','ondragover','ondragstart','ondrop','onmousedown','onmousemove','onmouseout','onmouseover','onmouseup','onmousewheel','onscroll');
public static $KEYBOARD_EVENT_ATTRIBUTES = array('onkeydown','onkeypress','onkeyup');
public static $FORM_EVENT_ATTRIBUTES = array('onblur','onchange','oncontextmenu','onfocus','onformchange','onforminput','oninput','oninvalid','onreset','onselect','onsubmit');
public static $MEDIA_EVENT_ATTRIBUTES = array('onabort','oncanplay','oncanplaythrough','ondurationchange','onemptied','onended','onerror','onloadeddata','onloadedmetadata','onloadstart','onpause','onplay','onplaying','onprogress','onratechange','onreadystatechange','onseeked','onseeking','onstalled','onsuspend','ontimeupdate','onvolumechange','onwaiting');
public static function getValidBodyAttrs() {
return array_merge(self::$BODY_ATTRIBUTES,self::$GLOBAL_ATTRIBUTES,self::$WINDOW_EVENT_ATTRIBUTES,self::$MOUSE_EVENT_ATTRIBUTES,self::$KEYBOARD_EVENT_ATTRIBUTES);
}
}
after creating this file I added a method _initView to the Bootstrap.php file pointed to by the index.php and application.ini at the root of the application directory:
protected function _initView()
{
// Custom_View extends Zend_View
$view = new Custom_View();
// Add it to the ViewRenderer
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper( 'ViewRenderer' );
$viewRenderer->setView($view);
return $view;
}
The new, extended Zend_View now allows adding your body tags along with some simple checking for validity. Modify your layout's body tag to get the attributes:
<body<?= $this->_getBodyAttrs(); ?>>
Once you have this set up you can add your body tags to any given view
in the controller with
$this->view->_setBodyAttr('key','val');
or in the view with
$this->_setBodyAttr('key','val');

Categories