ExtJs 4 + PHP on deployment - class loading - php

I am maintaining Zend application with ExtJS 3 based views. Recently, I am working on migrating to ExtJS 4 MVC based application.
Background
With ExtJS 3 I used to combine ExtJS library + all my JS files and include that in Zend layout (let's call that combine.js).
<script type="text/javascript" src="combine.js"></script>
All I needed to do was to met dependencies in combined file.
Now, trying to accomplish ExtJS 4 MVC approach with Zend generating my views, I am running into multiple problems with the new Ext.Loader. My Zend layout consists of
<script type="text/javascript">
Ext.application({
name: 'demo',
appFolder: 'app',
controllers: [
// controllers list here
],
launch: function()
{
// viewport + page items
}
});
</script>
Moreover, in HEAD section I still maintain the same approach to include one combined file (ExtJS 4 library + all my js files). In theory, I have all js dependencies met since I include the whole library before my code.
Problem
I am running into multiple problems with new class loading mechanism.
Let's assume I have only one controller with one view and one store on ExtJS side:
Ext.define('demo.myModule.controller.MyGrid', function() {
extend: 'Ext.app.Controller',
stores: [ 'demo.myModule.store.MyStore' ],
views: [ 'demo.myModule.view.MyStore' ]
...
});
Rendering such page ends up with Ext.Loader trying to fetch not existing resource :
GET http://myPage/demo/myModule/store/MyStore.js?_dc=1390226857962 404 (Not Found)
Disabling Ext.Loader ends up with :
Uncaught Error: Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. Missing required class: demo.myModule.controller.MyGrid
Since ExtJS 4 is a really popular library, someone must have hit the same stumbling block before. What is the proper way to tackle such problem ?
BTW. I am asking that question having already spent couple of days on ExtJS documentation + official tutorials, tried Sencha CMD but I fail to get what the exact problem is.
EDIT:
I have added a sample project showing the problem: https://github.com/mirfilip/extjs-zend. You can see app.js containing simple class demo.myModule.view.Panel. In application/layouts/scripts/layout.phtml you can see that the whole library + app.js is loaded (in order). When you try to render the project it will show the blank page. However, if you go to layout and uncomment lines 23-33 (and comment out appending of app.js in line 11) and render, it works well. The only difference is where my class is defined in. There should be no possible time race between classes as Ext.application creation is wrapped it Ext.onReady. Any ideas ?

I don't use Zend Studio, so I cannot give a specific answer. I will just show you my code, how I integrate ExtJs into my own homebrewed framework.
This is the html code on my development site, which will use Ext.Loader to load the classes dynamically.
<!-- <x-compile> -->
<!-- <x-bootstrap> -->
<link rel="stylesheet" href="bootstrap.css">
<script src="ext/ext-dev.js"></script>
<script src="bootstrap.js"></script>
<!-- </x-bootstrap> -->
<script src="ext/locale/ext-lang-fr.js"></script>
<script src="app.js"></script>
<!-- </x-compile> -->
This will then compile to :
<link rel="stylesheet" href="resources/Mb-all.css"/>
<script type="text/javascript" src="app.js"></script>
This snipped is found in the build/production/MyApp/index.php folder. I have then a build script that takes this file and copies it where it should be for the php framework to work.
I hope this will give you an idea to solve your specific problem.
Important: app.js is a autogenerated file by sencha cmd. It is not the same thing in the development environment and in the test environment.
In the development it just contains this text:
/*
This file is generated and updated by Sencha Cmd. You can edit this file as
needed for your application, but these edits will have to be merged by
Sencha Cmd when upgrading.
*/
Ext.application({
name: 'Mb',
extend: 'Mb.Application',
autoCreateViewport: true
});
In the production envrionment it contains the full, minified javascript source of the app.

Probably you have to indicate paths to Ext classes before your combined app js file. I'm using paths relative to domain root ('/app' not 'app').
<script>
Ext.Loader.setConfig({
paths : {
'demo' : '/app'
},
enabled: true
});
</script>
<script src="combine.js" />

Related

Using VueJS components in PHP

I want to mix basic HTML generated by Php and VueJS components without having to use VueJS all the way down to the lowest dom leaf.
The parent layout has the Vue app applied all the headers navs assides etc are Vue components and the main content on most pages are still plain HTML generated by PHP.
I want to upgrade small parts of the main content with Vue components but I cant use them once HTML has been used:
Php script generates the entire dom
<div id="app"> VueJS instance mounts here.
<Cats>This component works perfectly here.
<div id="main Content">More HTML content generated by PHP.
<Cats> Cats does nothing here.
<Cats> works perfectly fine in the upper DOM but after rendering some basic HTML the app will no longer populate components further down.
Php can render JS in a script tag but it's unable to use any imports.
Is there any way to get the Vue instance to treat all <Cats> tags as the Cats component regardless of where it is written on the page?
So far I have tried:
async components.
portals using mounting portals.
creating another Vue instance and mounting it to another ID.
Any ideas?
EDIT: The things I tried previously may be been blocked by the mishmash of multiple UI modernization attempts in this monolith I have inherited.
So I would not rule those out for others facing this situation.
If you are dynamically passing the template which is coming from an API or from any other source into your Vue instance. There is a way to access that via v-html attribute but before using that please have a look at note below.
Note that the contents are inserted as plain HTML - they will not be compiled as Vue templates.
Hence, As you are trying to bind/render the Component itself and it's not a plain HTML. So it will not processed by Vue's template compiler.
Possible solution is that you can get a component name and props from your PHP API instead of whole HTML template.
You can also achieve the same by using Vue compile option. Here is the demo :
Vue.component('Cats', {
props: ['msg'],
template: '<h3>{{ msg }}</h3>'
});
// Template coming from PHP
const template = `<div id="main Content"><Cats msg="Meow... Meow..."></div>`
var app = new Vue({
el: '#app',
data: {
compiled: null
},
mounted() {
setTimeout(() => {
this.compiled = Vue.compile(template);
})
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<Cats msg="Meow...">
</Cats>
<component :is="compiled"></component>
</div>
In the end, I had to manually add a JS file to the build configs containing a global window.ExtraVue with a setup function like so:
import Cats from 'files/Cats.vue';
window.ExtraVue = {
setup: function(data) {
new Vue({
el: '#extra-vue',
data: data,
components: {
Cats
},
template: '<Cats/>'
})
}
};
The setup function is then called at the very end of the PHP script.
<script>window.ExtraVue.setup(<?=json_encode($array)?>)</script>
The setup function can now create a new Vue instance for each component that needs to be out on its own.
Ideally, it would be great if VueJS could just replace matching tags with components.

How to integrate Reactjs frontend with php codeigniter application on apache server?

The CodeIgniter application was developed much earlier without plans to integrate ReactJS at that time. A later requirement was added to integrate another ReactJS project with this backend and replace the current frontend (views).
The CodeIgniter application is not done as a RESTful API. The .php view files could not be replaced with .js files of the reactjs app as the server is Apache.
Running a nodejs server would not render the CodeIgniter views.
Bootstrap, jquery, and simple javascript can be included within the view of the CodeIgniter application. But is it possible to replace the PHP view files in CodeIgniter with javascript files?
The PHP view files do not need to be replaced with js files. JavaScript can easily be added to PHP files using <script> tags. Below is the Add React in One Minute demo in a CodeIgniter app.
To integrate the React demo into CodeIgniter start with a simple controller - React.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class React extends CI_Controller
{
public function index()
{
$this->load->view('react_view');
}
}
The "view" file is straight from the React demo but it's put in a .php file instead of .html.
The only change made to the demo code is in the script tag at the bottom of the page. My assets folder is on the same level as CodeIgniter's /application folder. There are subfolders in assets for css, js, and images.
/public_html
/application
/system
/assets
/js
/css
/img
So I've changed the src for the tag that loads like_button.js to work with my file layout.
The "view" file react_view.php
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Add React in One Minute</title>
</head>
<body>
<h2>Add React in One Minute</h2>
<p>This page demonstrates using React with no build tooling.</p>
<p>React is loaded as a script tag.</p>
<p>
This is the first comment.
<!-- We will put our React component inside this div. -->
<div class="like_button_container" data-commentid="1"></div>
</p>
<p>
This is the second comment.
<!-- We will put our React component inside this div. -->
<div class="like_button_container" data-commentid="2"></div>
</p>
<p>
This is the third comment.
<!-- We will put our React component inside this div. -->
<div class="like_button_container" data-commentid="3"></div>
</p>
<!-- Load React. -->
<!-- Note: when deploying, replace "development.js" with "production.min.js". -->
<script src="https://unpkg.com/react#16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js" crossorigin></script>
<!-- Load our React component. -->
<script src="assets/js/like_button.js"></script>
</body>
</html>
/assets/js/like_button.js
'use strict';
const e = React.createElement;
class LikeButton extends React.Component {
constructor(props) {
super(props);
this.state = { liked: false };
}
render() {
if (this.state.liked) {
return 'You liked comment number ' + this.props.commentID;
}
return e(
'button',
{ onClick: () => this.setState({ liked: true }) },
'Like'
);
}
}
// Find all DOM containers, and render Like buttons into them.
document.querySelectorAll('.like_button_container')
.forEach(domContainer => {
// Read the comment ID from a data-* attribute.
const commentID = parseInt(domContainer.dataset.commentid, 10);
ReactDOM.render(
e(LikeButton, { commentID: commentID }),
domContainer
);
});
Here's a boilerplate that you can use.
https://github.com/cyruzin/codeigniter-react-boilerplate
React is used for single page applications. Codeigniter is a PHP framework. Nobody forbids you to include react apps inside codeigniter. The react app polls data from API provided by codeigniter. You can use multiple codeigniter controllers or views to define different react states, or you can just use one controller, one view and multiple models and define states with react alone.
React is not in opposition to codeigniter. Codeigniter doesn't care if you use jquery, angular or react. From the view on it's not a codeigniter's business.

How to add version to all style and JS tags(includes) inside Views in Codeigniter php

Whenever I release a new version of the website to the clients, I have to instruct them to clear their browser cache so that they see the updates.
Now, after searching I found that I have to add versions to style and Js files before releasing the new version so that my client's browser will detect revision and fetch the latest css/js resources. This is explained here
Example:
<script type="text/javascript" src="include/232/init.js"></script>
<script type="text/javascript" src="include/init.js?232"></script>
Where 232 is your modifiable version number that should be changed whenever you release new code.
After updating the versions, things are working fine. But I do not want to open up all the views and update the versions manually.
Instead I am searching for some logic which will update/set a new version to the Style / Javascript tags inside all the Views located in Views Directory.
Is there a way to do that ??
You can add a version like setting in your config.php file:
$config['curr_ver'] = "1.5";
Then in your files, you can write them this way:
<script type="text/javascript" src="include/init.js?v=<?=$this->config->item("curr_ver");?>"></script>
That should render:
<script type="text/javascript" src="include/init.js?v=1.5"></script>
This should be a just one time refactoring job, and when you need to change to a new version, you just update the setting in the config.php file to 1.6 or another value.
You can add a version in your config/constants.php file as a constant:
define("UPDATE_VERSION", "2");
Then you can add this line to your script and style files:
<script src="include/init.js?v=<?= UPDATE_VERSION ?>"></script>init

Best way to represent CSS & JS files for a big project

What is the best way to represent CSS files for a large project
I am using CodeIgniter and there would be 100's of views and almost of them have different structure so I have a lot of options here but I don't know what is the best one so please help
Make a single file for CSS and single file for JS
Make a CSS file for each view and JS for each view
Make a simple database table to hold the associated files for
each method
for example
id ----- method_name ---- files (I will normalize it )
1 /test/first first.css,first.js
and so on
or make a PHP function get the associated files as text from PHP
for example
<?php
function get_assoc($view)
{
switch($view):
case '/test/first':
echo "<script>alert(); </script><style>p{font-weight:bold;}</style>";
break;
endswitch;
}
?>
Also what about caching? Performance is a big factor.
Thanks.
I like to seperate each section reset/typograpy/forms/tables, this way I dont get lost. Dont be afraid to use as many different files as you need ( for development purposes ).
Once your ready to go into production/live mode, grab the "build tool" from "html5boilerplate" and compress all your css into one file, same for js. This will also minify your code and cache your files. just keep your un-compressed files handy incase you need to do a major edit
<!-- CSS -->
<link rel=stylesheet href="assets/css/reset.css" >
<link rel=stylesheet href="assets/css/typography.css" >
<link rel=stylesheet href="assets/css/tools.css" >
<link rel=stylesheet href="assets/css/tables.css" >
<link rel=stylesheet href="assets/css/forms.css" >
<link rel=stylesheet href="assets/css/plugins.css" >
<!-- Script -->
<script src="assets/js/modernizr2.0.js"></script>
<script src=https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js></script>
<script src="assets/js/plugins.js"></script>
<script src="assets/js/tools.js"></script>
<script src="assets/js/tables.js"></script>
<script src="assets/js/forms.js"></script>
<script src="assets/js/functions.js"></script>
I then like to wrap each (js) file as an object, again this helps with readability.
example:
(function($){
var ToolsObj = {
init : function(){
this.tooltip();
this.tabs();
this.pagination();
this.alerts();
this.dropdowns();
this.lightbox();
},
tooltip : function(){
//tooltip code
},
tabs : function(){
//tabs code
},
pagination : function(){
},
alerts : function(){
//alert messages code
},
dropdowns : function(){
//dropdown-menu code
},
lightbox : function(){
//lightbox code
}
}
$(function(){
ToolsObj.init();
});
})(jQuery.noConflict());
Hope this gives you some insight into my workflow.
You may also want to check if each element exists in the document before running the objects.
Database = no
Don't use the database for this. The CSS/JS files needed to display a view are directly tied to the source code, so keep that info in the source (particularly if you're using an SCM like Git or SVN).
CSS/JS = presentation
As these files are related to presentation/UI, I'd recommend delegating the "responsibility" of loading them to the views themselves. The controllers & models shouldn't have to "know" anything about the CSS/JS required to display the view.
Be modular
Organize the files into discrete modular units. Don't have a separate CSS/JS file for every view UNLESS you truly have completely separate functionality on every single view. The more you share these files among views, the better off you'll be.
Leverage caching, rather than fighting it
I know it's a pain in the ass to rename a file every time you modify it, but it really is a good approach. Using cache invalidating approaches (like URL?time=...) simply puts extra strain on the server and clients for no good reason. Just take the two seconds to rename your "styles.css" file to "styles_v2.css". You'll thank yourself later. (And remember, you don't have to rename it for every single dev change--only when it's stable enough for QA / production).
Premature optimization = root of all evil
Finally--and most importantly--NEVER PREMATURELY OPTIMIZE! I've seen way too many people minify and gzip their asset files all the time, only to have them overhauled a few days later. Either create a true build process, or wait until things stabilize to worry too much about the fine tuning.
Do you already make a page database call to figure out which views should be used etc? May want to have a main js and css that would be used for all pages, then individual ones linked via DB that are specifically used only by certain views.
As for caching... These files will be cached by browsers as long as they have the same request name. I typically auto-version these with a view method that looks something like:
function autoversion($filename) {
$time = filemtime($filename);
return $filename . '?v=' . $time;
}
If you have a build system that can version these files for you, you will get a small performance gain.

Zend Framework: Enable jQuery in single view

Currently working with ZF and ZendX_JQuery.
As I understand, script links to Google's CDN JQuery are only included in the <head> section of a view if ZF JQuery is referenced in some way in the MVC.
However, I'm working with 'Cloud Zoom', a JQuery library for image zooming.
The view I wish to include Cloud Zoom in has no reference to JQuery, and therefore the script links are not included in the head. How can I make ZF include the script links in the head section of the page without explicitly including any ZF JQuery references in the MVC?
from http://framework.zend.com/manual/en/zendx.jquery.view.html
To access the javascript we have to
utilize the jQuery() functionality.
Both helpers already activated their
dependencies that is they have called
jQuery()->enable() and
jQuery()->uiEnable()
i have this code in my layout
if ($this->jQuery()->isEnabled()) {
$this->headScript()->appendFile('/scripts/jquery.ui.datepicker-it.js');//localizazione di DatePicker
echo $this->jQuery()->setRenderMode(ZendX_JQuery::RENDER_JAVASCRIPT | ZendX_JQuery::RENDER_JQUERY_ON_LOAD);
}
so i guess you have to do something like $this->jQuery()->enable()->enableui()

Categories