Where to put common logic in cakephp app - logic

This is something I have struggled with for a while to get my head around
I have a shell which at the moment grabs data from a 3rd party, processes it and saves processed data into my db. The processing can save to related tables as well.
I also want to have some way of submitting data via chrome extension to be processed in the same way. The data is going to be in the same format in both scenarios so I was hoping to move the logic I have in my shell into something that both a shell and controller can use.
Part of my processing involves loading any currently saved data in some situations too - and I found that I can't use loadModel unless I am in a controller?
So where should this logic go, and how do I make sure that solution has access to all the part of the framework I need still?

You can create an Utility folder under src containing php files.
Here you can define your namespace of class and can instantiate easily.
You can use statements also.
--src
|--Utility
|--Example.php
<?php
namespace App\Utility;
class Example
{
function __construct() {
//constructor
}
function demo() {
//function for specific task
}
}

Related

Dynamically get the public path for a workbench package in laravel

I'd like to get the path to a package public directory (css etc) based on the package alias.
Is there anything already built into the laravel framework?
In other words something like:
public_path('myalias');
When I'm talking about alias, you would typically "alias" a module by adding the following within your service provider's boot method:
$this->package('namespace/package','alias_name');
For those wondering why someone might want to do this:
We are running a multi domain/subdomain application that makes use of a central piece of code for all of the domains and then specific packages per domain (I'll refer to them as funnels).
Each funnel has its own controllers that can possibly extend base controllers to implement their own functionality while re-using code where they can. They also have their own views.
The funnel refers to its own views by way of something like:
View::make('funnel::path.to.view')
The way we accomplish this is by doing some business logic on page load to only load the FunnelServiceProvider related to that particular domain and aliasing it to "funnel". This way our base controllers can also refer to funnel and not be tied to a particular packages views,includes,blocks etc.
My hope is to do something similar on the views so that I can simply call something like get_funnel_path() to get the path to the funnel that is currently being loaded.
The value could then be used to load css,js,images etc without worrying about the funnel path.
This would allow us to simply copy and paste views from one domain to the next without having to modify all of the paths in potentially multiple files. We could also make use of globally included files in all/most of the views.
An example of this might be the head. The head section should be the same for 99% of the files, however the path where it loads its resources should change based on the funnel.
We use the same naming conventions for css files as well as use sass, imports, merging for all of the funnels; so only the path needs to change.
You can do something like this although it will only work with your own packages and require a bit of work. Because the alias is not really stored somewhere you can easily access you have to do that yourself.
First create some kind of class to store your package names in. I called mine PackageManager:
class PackageManager {
private $packages = array();
public function addPackage($fullName, $alias){
$this->packages[$alias] = $fullName;
return $this;
}
public function getPublicPath($alias){
if(!isset($this->packages[$alias])) return public_path();
$path = 'packages/' . $this->packages[$alias];
return public_path($path);
}
}
Now let's register that class as a singleton in a service provider:
$this->app->singleton('packagemanager', function(){
return new PackageManager();
});
Then, in every package you want to register, add this call in the boot method right next to $this->package():
$this->app['packagemanager']->addPackage('vendor/package', 'alias');
After that you can do this anywhere in your application:
app('packagemanager')->getPublicPath('alias');
If you want a shorter syntax, add this helper function somewhere:
function public_package_path($alias){
return app('packagemanager')->getPublicPath($alias);
}
And just do:
public_package_path('alias');

How to prevent duplication of code

We're currently developing an E-commerce site. We have a public and admin module.
Sometimes we offer the same functionality in both modules like viewing of products or creating of orders. But there are also some functionalities that is present in either public or admin like adding of products (which is in admin).
Our problem is that common functionalities lead to duplication of logic. We need to implement it in both modules.
One way of solving the problem is to make use of layers. So what we did was move the common logic into the Model. However, the controller is still duplicating codes like the one shown below:
public function invoice() {
$this->Invoice->create();
$this->Invoice->setCustomer($this->getCurrentUser);
$invoice_items = // get list of items from post
$this->Invoice->setItems($invoice_items);
$this->Invoice->save();
}
My question is, is it wise to create a webservice that will encapsulate this logic and you just have to call it from the admin and public modules..
How does Magento implement the public and admin panels. And how does it manage its logic..
I would recommend you not to do that. From your question, it is not exactly clear what sort of 'logic' are you referring to, but it does not seem too complex from your example. In general, business logic should be coded within the Model, controller, or Helper portions of the code. It can even reside in a separate extension as long as you set dependencies properly in the main xml file of the extension.
It seems that you may benefit from placing your logic in a helper class. The default helper file resides under /app/code/community/company/extension-name/Helper/Data.php. Then you can call the helper method anywhere in the backend (Block, Module, or controllers) by using this piece of code:
Mage::helper('extension-name')->getLogic()
Or you can call the same helper method from the view (phtml files) like this:
$this->helper('extension-name')->getLogic()

Should directory access be taken care of by models or controllers?

I have an app that requires adding and deleting image files in a simple interface. Should the controller be the one that directly deletes these files, or should deleting files be in the domain of my models?
I ask because files could be viewed as a type of "data". Just want to know what the convention is.
It depends on how your models are designed, but overall I think it's model's matter.
This is because even if adding / deleting is just a plain filesystem actions wrapper right now, it may involve database actions / revision support in the future: this way the controller is agnostic to what really happens.
for f in filesToDelete:
f.delete();
endfor;
Where delete could be:
public function delete()
{
unlink(this.path);
}
or
public function delete()
{
db::remove(this.path); // or whatever
unlink(this.path);
}
And if you need batch operations, you just model a Folder / SmartFolder class in order to perform them.

CodeIgniter - where to put functions / classes?

Am having problems understanding where classes should be kept in CI. I am building an application that describes / markets mobile phones.
I would like for all of my functions (i.e. getphone, getdetails etc.) to reside in one class called Mobile - I understand that this file should be called Mobile.php and reside in the controllers folder.
Can I then have multiple functions inside Mobile.php? E.g.
public function getphone() {
xxx
xx
xx
}
public function getdetails() {
xxx
xx
xx
}
Or do I need to put each function in its own class?
I'd really appreciate looking at some sample code that works. I've been going through the documentation and google for a few hours, and tried all sorts of variations in the URL to find a test class, but without much luck! I've even messed around with the routes and .htaccess...
All I am trying to achieve is the following:
http:///model/HTC-Desire/ to be re-routed to a function that accepts HTC-Desire as a parameter (as I need it for a DB lookup). The default controller works fine, but can't get anything to work thereafter.
Any ideas?
Thanks
Actually it works like this:
Controllers and Models go to their perspective folders as you know it
If you want to create functions that are not methods of an object, you must create a helper file. More info here :
http://codeigniter.com/user_guide/general/helpers.html
Now if you want to create your own datatypes (classes that don't extend Models and Controllers), you add them to the library folder. So if let's say you want to create a class "Car" you create this file:
class Car{
function __construct(){}
}
and save it in the libraries folder as car.php
To create an instance of the Car class you must do the following:
$this->load->library('car');
$my_car = new Car();
More information on libraries here:
http://codeigniter.com/user_guide/general/creating_libraries.html
Yes, you can have as many functions in a controller class as you'd like. They are accessible via the url /class/function.
You can catch parameters in the class functions, though it's not advisable.
class Mobile extends CI_Controller{
public function getPhone($phoneModel=''){
echo $phoneModel;
//echo $this->input->post('phoneModel');
}
}
http://site.com/mobile/getPhone/HTC-Rad theoretically would echo out "HTC-Rad". HOWEVER, special characters are not welcome in URL's in CI by default, so in this example you may be met with a 'Disallowed URI characters" error instead. You'd be better off passing the phone model (or any other parameters) via $_POST to the controller.
Classes can exist both as Controllers and Models, as CodeIgniter implements the MVC pattern. I recommend reading more about that to understand how your classes/functions/etc. can best be organized.
Off the top of my head, Pyro CMS is an application built with CodeIgniter and the source code is freely available. I'm sure there are others.
I think it's best you handle it from one perspective, that is; create a utility class with all your functions in it.
The answer to the question of where to put/place the class file is the "libraries" folder.
This is clearly stated in the documentation. Place your class in the libraries folder.
When we use the term “Libraries” we are normally referring to the
classes that are located in the libraries directory and described in
the Class Reference of this user guide.
You can read more on creating and using libraries Creating Libraries — CodeIgniter 3.1.10 documentation
After placing the newly created class in the libraries folder, to use just simply load the library within your controller as shown below:
$this->load->library('yourphpclassname');
If you wish to receive several arguments within you constructor you have to modify it to receive an argument which would be an array and you loading/initialization would then be slightly different as shown below:
$params = array('type' => 'large', 'color' => 'red');
$this->load->library('yourphpclassname', $params);
Then, to access any of the functions within the class simply do that as shown below:
$this->yourphpclassname->some_method();
I hope this answers your question if you have further question do leave a comment and I would do well to respond to them.

Symfony Actions Namespacing, or a better way?

In Rails, you can organize controllers into folders and keep your structure nice with namespacing. I'm looking for a similar organizational structure in Symfony 1.4.
I was thinking of organizing multiple actions.class.php files in an actions folder, but all I came across was using independent action files, one for each action... like this:
# fooAction.class.php
class fooAction extends sfActions {
public function executeFoo() {
echo 'foo!';
}
}
But I'd have to develop a whole new routing system in order to fit multiple actions into that file, which is... silly.
Really I'm just looking to make Symfony into Rails, (again, silly, but I'm stuck with Symfony for this project) so I'm wondering if there's a better way....?
Thanks.
An alternative action syntax is
available to dispatch the actions in
separate files, one file per action.
In this case, each action class
extends sfAction (instead of
sfActions) and is named
actionNameAction. The actual action
method is simply named execute.
class indexAction extends sfAction
{
public function execute($request)
{
// ...
}
}
A Gentle Introduction to symfony - chapter 06: Inside the controller layer, subsection Alternative Action Class Syntax

Resources