Is possible use an external 'model-config.json' file at Strongloop - models

Actually, Strongloop allows developers to use default file for model-config.json. Inside it, there is a plenty of model definitions.
Why would I use an external model-config.json?
Because, I have a few projects sharing same models. Currently I am able to point models to an parent folder, this way:
'model-config.json'
{
"_meta": {
"sources": [
"loopback/common/models",
"loopback/server/models",
"../../shared-models-project/common/models", // this is external to the project
"../common/models",
"./models"
], ...
}
But after doing this change, I noticed that all models are also referenced in model-config.json file. Then the solution could be using an external model-config.json, located at shared-models-project/server/model-config.json instead of ./server/model-config.json.
But... is this possible? Any alternatives??

Loopback will also look for model-config.js (link), so you could create that file with something like:
module.exports = require('../../shared-models-project/server/model-config.json')
Is that what you meant?

Related

Where is the correct place to locate custom functions in Laravel?

In my projects I usually create several functions, which some of them are debug functions (I use microtimes, var_dumps, print_r, ...) to customize the data, and others are functions that end up being used very often in the project (for example functions that do certain things with session variables, that works with an object / array and return it in a certain way, etc.).
I always have doubts about where I should include these functions. So far the second type of functions (work with session variables, general scope functions that alter project variables) put them in a controller (CommonController), while the first type of functions (debug functions in the vast majority) I thought to put in a helper.
However, I still have serious doubts about whether both groups of functions should be placed on those sites.
Please, someone who can guide me a little?
Thank you!
Follow this steps:
create a helpers.php file to app folder
and this code to composer.json file :
"autoload": {
...
"files": [
"app/helpers.php"
]
},
For example :
helpers.php
function showTest(){
dd("ok");
}
UserController.php
public function index(Request $request) {
showTest();
}

Can I access a full composer package from a link when responding to an event

I have created an event handler to be called by composer when processing composer.json:
"post-install-cmd": [
"Company\\Library\\Layer\\Handler::script"
],
The relevant, corresponding code is:
class Handler {
public static function script(Event $event) {
$aRequires = $event->getComposer()->getPackage()->getRequires();
foreach ($aRequires as $oRequire) {
// process each required package
}
}
}
Each $oRequire is of type Composer\Package\Link and contains basic information about the required package.
I'd like to be able to access the full package information, eg. a sub-class of Composer\Package\BasePackage. Is this possible? That is, given a Link and the target name, can I lookup (resolve?) the target name to its full package in this context?
I've read a fair bit of the doco and I cannot tell either way.
After earning the Tumbleweed badge for this question, I decided it need an answer. Obviously no-one came forward with a solution and despite further effort on my part, I could not find one either. So I conclude there is no direct way to achieve what I want.
The information I'm after however, is in the composer.lock file. So if this file has been successfully created, you could load it (it's JSON, so this is trivial) and then lookup the desired info.

Dynamically require one chunk per directory for on-demand (async) files in webpack?

Problem
This is how the app behaves:
every folder corresponds to a dynamic "feature" in the app.
features are independent of each other. (Inside each folder, none of the files have dependencies on other folders. However, each folder may use the same common libraries like jquery.)
not all features are needed all the time
within each folder, the files are not necessarily dependent on each other (but it makes sense to bundle them together because that's how a "feature" works)
the number of features is not fixed ... so a manual process where you have to manually update various configurations/files each time you add/remove a feature is NOT ideal
Desired Solution
Given what I described, what seems to make sense is to create chunks for each feature/folder and then load each chunk asynchronously (on demand) as needed by the app.
The problem is that this doesn't seem easy with webpack. I'd like to be able to do this
require.ensure([], function() {
var implementation = require('features/*/'+feature);
//...
where each feature (folder) goes in one chunk.
Unfortunately, if I'm understanding require.context correctly, that's not possible.
An alternative?
A possible alternative is the following:
use a single config file that lists each feature (we actually already use this),
use the config file to auto-generate a module that requires each folder asynchronously. (Basically, the "module" is a factory that the app can use to load each feature.)
add an entry point to the auto-generated module (force the chunks to be built).
So to summarize, add a build step that generates a factory that asynchronously load features. The problem is that this seems unnecessarily complex and I'm wondering if there's an better way to implement the solution. Or am I on the wrong track? is there a completely different solution?
Code
Folder structure
features
sl.graded.equation
graded.equations.js
graded.equation.edit.js
graded.equation.support.js
sl.griddable
griddable.js
griddable.edit.js
//...
Config file
{
"sl.graded.equation": [ //basically lists the feature "entry points" (not every file)
"sl.graded.equation",
"sl.graded.equation.edit"
],
"sl.griddable": [
"sl.griddable",
"sl.griddable.edit"
]
//...
}
Auto-generated factory
module.exports = function(feature, callback) {
switch(feature) {
//we can get fancy and return a promise/stream
case 'sl.graded.equation':
require.ensure([], function() {
var a = require('sl.graded.equation');
var b = require('sl.graded.equation.edit');
callback(a,b);
}
//...

Best Practices for Laravel 4 Helpers and Basic Functions?

I'm trying to understand the best place to put a global function in Laravel 4. For example, date formatting. I don't think making a facade is worth it as facades are too modular. I've read articles about creating a library folder and storing classes there but that also seems like a lot for a simple function. Shouldn't a 'tool' like this be available in Blade templates?
What are the best practices for something like this and how do I make it available to Blade templates?
The ugly, lazy and awful way: At the end of bootstrap/start.php , add an include('tools.php') and place your function in that new file.
The clean way: Create a library. That way it'll be autoloaded ONLY when you actually use it.
Create a libraries folder inside your app folder
Create your library file, create a class in it, and add static functions to it
Option 1: Edit start/global.php to add app_path().'/libraries' to the ClassLoader::addDirectories( array.
Option 2: Edit composer.json to add "app/libraries" to the autoload array. Run composer dump-autoload
Call your class and static functions from your views.
About your options, quoted from the global.php file
In addition to using Composer, you may use the Laravel class loader to
load your controllers and models. This is useful for keeping all of
your classes in the "global" namespace without Composer updating.
You can combine both options, where the Laravel class loader will automatically search for classes in the registered directories (Option 1, easier) and Composer will keep record of all the classes but only after you update it (Option 2, might improve performance).
My way of doing this is to create a new folder in the /app directory in the root of your Laravel 4 project. Then add this folder to the first array of the /app/start/global.php file like so:
<?php
ClassLoader::addDirectories(array(
app_path().'/commands',
app_path().'/controllers',
app_path().'/models',
app_path().'/database/seeds',
app_path().'/classes', // This line is the one I've added.
));
As long as the folder structure within the new /app/classes folder follows your namespacing convention. Laravel 4 will autoload all the classes/files within this folder. This way there's no need to dig into any composer files or run composer command.
Not sure if this is best practice but it certainly works.
If you created a simple file called /app/classes/Helpers/Helper.php such as this:
<?php namespace Helpers;
class Helper {
public static function helloWorld()
{
return 'Hello World';
}
}
All you would need to do is call Helpers\Helper::helloWorld();
You could also alias this helper class in your /app/config/app.php file. Just add something like this to the end of the aliases array:
'Helper' => 'Helpers\Helper'
Laravel's helpers.php method is to add it to your "files" in composer.json (https://github.com/laravel/framework/blob/master/composer.json):
"autoload": {
"classmap": [
...
],
"files": [
"app/libraries/helpers.php"
],
},
What I do is to create small classes (a few methods per class, one line per method, everything extended from something and DRY, that's my goal),
class ExtendedCarbon extends Carbon\Carbon {
public function formatDDMMAAAA($date)
{
/// format and return
}
}
save them to them in app/libraries and add to composer.json:
"autoload": {
"classmap": [
...
"app/libraries",
...
],
},
Execute
composer dump
And then just use them wherever you need
$formatted = (new ExtendedCarbon)->formatDDMMAAAA($date);
Watch this video about refactoring: http://www.youtube.com/watch?v=DC-pQPq0acs
By the way, I'm kind of sure it was just an example, but you might not need a helper to format dates, since all dates in Laravel are instances of Carbon (https://github.com/briannesbitt/Carbon) and it has loads of methods to format date and time.
You can also use View::share() together with closures to achieve this - I just posted about this: http://www.develophp.org/2014/07/laravel-4-blade-helper-functions/
Added benefit: You don't need to create an extra class and also keep the global namespace clean.

Separate layouts and namespaces for frontend/backend in Zend application

I had to develop a CMS using Zend Framework and I used the default namespace defined in my boostrap for my backend:
autoloaderNamespaces[] = "Application_"
Now I want to develop the frontend, but I don't know how to do it, since I have access to my backend from the /public/ directory.
Then I would like to use a different layout for my frontend than the one I use for the backend access. So I found this post but I don't know if I have to change/add (and then how to change) the module of my backend, or if I have to create a second module that I will use for my frontend
my file tree is like this :
So if I create a frontend module, shall I create a frontend directory next to the applicationdirectory ?
EDIT : I created 2directories pub and frontend next to the application directory. In pub/index.php I instanciated the bootstrap with the application/configs/application.ini file with a different APPLICATION_FRONT_ENV :
[frontprod : production]
bootstrap.path = APPLICATION_FRONT_PATH "/bootstrap.php"
bootstrap.class = "Bootstrap"
resources.frontController.controllerDirectory = APPLICATION_FRONT_PATH "/controllers"
autoloaderNamespaces[] = "Frontend_"
resources.layout.layout = "layout"
resources.layout.layoutPath = APPLICATION_FRONT_PATH "/layouts/scripts"
[frontdev: frontprod]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.frontController.params.displayExceptions = 1
and in the frontend/bootstrap.php I loaded models from applicationdirectory :
public function _initAutoloader(){
$baseAutoload = new Zend_Loader_Autoloader_Resource(array(
'namespace' => 'Application',
'basePath' => realpath(dirname(__FILE__).'/../application')
)
);
}
And it seems to be working fine =)
thank you !
In Zend Framework you can organise your app in modules, wich suits very well to your needs. Unfortunately the doc doesn't emphasize enough the importance of this concept, and how you should implement it from day one.
Modules allows you to regroup under a same module folder everything that is related to this module only, and this way to isolate "parts" of your app in logical groups.
In your case it would be "back" and "front", but you could also have a "forum" module or let's say a "shop" module.
In the urls point of view, the default routing of a modular structure is example.com/module/controller/action, but using hostname routes you can also have www.example.com pointing to your "front" module and admin.example.com pointing to your backend.
Have a look at the poor documentation section about modules, and don't panic, you won't have to rename everything if you move your current controllers, views and models in the "default" module.
There is an other alternative that could suit well for a backend/frontend logic, but not if you want to split your code in more logical parts (forum, blog, shop,...). You just create a second application folder (you would name 'frontend') next to the 'application' folder, and a second public directory (where you can symlink your assets folder if you use the sames), and a different namespace.
To be able to autoload your 'Application_' classes in your frontend code, just add and configure a Module Autoloader in your frontend bootstrap. The code is quite simple :
//in your frontend/Bootstrap.php
public function _initAutoloader(){
new Zend_Loader_Autoloader_Resource( array(
'namespace' => 'Application_',
'path' => realpath(dirname(__FILE__).'/../application'
)
);
}
For the application.ini config file i would recommend, instead of duplicating it, that you create a section [frontprod : production] section where you override your backend settings (and a matching [frontdev: frontprod] for your local settings).
I hope this helped. There is so much to say about all the topics introduced here that you should first have a look at this, then comment this answer with more specific questions about the problems you may encounter, and i'll extend the answer.

Resources