Where to store global data? - php

I'm writing this small blogging platform in Laravel 4.1, for learning purpose. My first obstacle is, I don't know where the global data (ie. dynamic blog settings, plugin and theme array) should be put, so that I can access them from anywhere (similar to how $wpdb in WordPress works - we only need global $wpdb; to access it).
Of course $GLOBALS works, but we know that it's evil and should be avoided. Also, I'd like everything to be as Laravel'y as possible.
Have tried:
App::bind('settings', []); // error
App::instance('settings', []); // how to populate and retrieve it back?
Any ideas? Thanks in advance.

If this is not something you need to keep between sessions, you can use:
Config::set('myglobals.name', 'An Phan');
And then
var_dump( Config::get('myglobals.name') );
But you also have to think a bit and think why would you need globals in the first place. Take a look at this: http://c2.com/cgi/wiki?GlobalVariablesAreBad.
EDIT
This is not a workaround, this is something Laravel provides out of the box and you can use yourself. Usually the purpose of Config would be having configuration files to be used by your application, but sometimes you just need to change those values during the request, that's why Laravel provides also a set() method.
Unfortunately WP has an old codebase and if you are trying do things the way WP does things, you're goind the in wrong path.
What would be the Laravel way depends on what you're trying to accomplish with your project, so you'll have to tell a little bit more about it.
The mindset to start with is: "I don't need globals" and when you get to a point where a global is needed, you ask yourself "how do I do this without using a global?".
Usually, you just need global values if you have settings to store. If it's something that you have to use to set a state during a request, you need to use objects. You can have global objects in Laravel, you can have singletons (objects that has only one instance in the whole application), you can create properties objects:
class SidebarProperties {
private $width;
public function __construct($width)
{
$this->width = $width
}
public getWidth()
{
return $this->width;
}
}
So you have an uncountable number of way to not use globals, you just have to think about your project and pick the one is best at that moment.

Well, global in a Laravel context means relative to Application, if you are not writing anything that "lives" outside of Application context.
There are couple of ways in which you can make you data available to application. But first, you have to make decision what kind of "globals" do you need ?
First and most important rule is that any change that you make besides Application specific folder structure, has to be told to composer.
Second, without making any changes, Laravel has default locations for most important parts of any "ordinary" web application.
Application folder structure is pretty self descriptive, but in short:
Configurations belongs to app/config
Models to app/models
Views to app/views
Controllers to app/controllers
Database to app/database
Routes to app/routes.php
If you follow this basic structure, you can create amazing web-apps. these folders and files are already namespaced and classes inside them are auto resolved. In you example you were trying to bind something to application, which is redundant in you case. Bindings to container are used in cases when you want to add some new classes and functionality to existing structure.
In short:
create you first route in routes.php like this:
Route::get("GET",function(){
return "my first route";
})
And from that point follow basic MVC flow, which is no different then most frameworks. Laravel is talking to you, just open you ears :)
And if you stack, just ask here, somebody will help.

Related

What's the reason behind using routes file in modern frameworks?

In modern web frameworks (Laravel, Symfony, Silex, to name a few), there seems to be a pattern of using a routes.php file or similar to attach URIs to controllers. Laravel makes it a bit easier with an option to use PHP annotations.
But to me all this feels like a bit of a code repetition, and when you are creating/modifying controller logic, you have to keep routes file always at hand. Interestingly, there's a simpler way I saw in several old frameworks, and I used to use this in my old projects as well:
Controller. All classes in src/controllers folder (old way) or all classes in YourApp\Controllers namespace are being automatically mapped to the first part of the URL by adding "Controller" to it. Example: /auth gets mapped to AuthController, /product/... — to ProductController, and / — to default IndexController.
Action. Action is the second part of the URL, and it gets mapped to the method name. So, /auth/login will call AuthController::loginAction() method. If no second part provided, we try indexAction(). Don't want people to access some internal method? Don't make it public.
Parameters. Next parts of the URL are being mapped to the arguments of the method; if there are Application and/or Request type hintings in the argument list, they are skipped so they can be properly injected; we can access GET/POST variables as usual through Request.
Here's the full example, using all these features together:
URL: https://example.com/shop/category/computers?country=US&sort=brand
namespace MyApp\Controllers;
class ShopController extends BaseController {
public function categoryAction(Application $app, Request $req, $category, $subcategory = null) {
echo $category; // computers
echo $subcategory; // null, it's optional here
echo $req->get('country'); // US
echo $req->get('sort'); // brand
}
}
I'm sure it seems to lack some familiar features at first, but all features that I can think of could be easily added if needed — using attachable providers, connecting middlewares, branching controllers to subcontrollers, specifying HTTP methods, and even performing a bit of a pre-validation on the arguments. It's very flexible.
This approach would really speed up the routing creation and management. So besides having all the routes in one file (which is also not always true, considering various providers, using ->mount() in Silex or bundles in Symfony), what are the reasons modern frameworks seem to prefer this way of doing MVC routing over the simpler way I've described? What am I missing?
I'll speak here from Symfony/Silex perspective:
Decoupling. routes.php provide separation of URL mapping and controllers. Do you need to add or change URL? You go straight to routes.php. Very handy if you want to change a lot of them.
Flexibility. Generally, routes.php is a bit more flexible approach. SEO might go crazy and might require you to have route like /shop_{shopName}/{categoryName}/someStaticKeyword/{anotherVar}. With routes.php you can easily map this to your code, but this might become a problem if your routes are directly mapped to the code. Even more, you can have this only controller, you don't need to write controllers for each slash part. You can even have different controllers handling the same URL with different variable parts, for example /blog/[\d]+ or /blog/[a-z-]+ being handled by different controllers (one might generate redirect to another). You might never need to do something like this, but this is just a demonstration of flexibility of this approach - with it anything is possible.
Validation. Another thing to consider is that routes.php provide simple means of validation via ->assert method. That is, routes.php does not only map URLs to controller methods, but also ensure that these URLs match specific requirements, and you don't have to do this in code (which in most scenarios would take a bit more code to write). Also, you can create default asserts for some variables, for instance, you may ensure that {page} or {userId} are always \d+, single line in routes.php that would take care of all usages of {page} or {userId}.
URL Generation. One more feature of routes.php is url generation. You can assign any route any name (via ->bind() method) and then generate URLs based on that name, and providing variables for parts of URL that change. And once we have this system and use URL generator throughout our code we can change URLs as much as we want, but we won't have any need to edit anything but routes.php. And once again - these are flexible names, that you won't have to change everywhere throughout your project once URL has changed and you are not limited choosing the name. It might be much shorter than the URL, or a bit more verbose.
Maintainability. Say, you might want to change some urls (as in example above - from /blog/[\d+] to /blog/[a-z-]+. Also, you might want to keep both of them for some time, and make old one redirect to the new one). With routes.php you simply add a new line and add a todo memo to remove it in some time if you want to remove it later.
Sure, all of this might be achieved with any aproach. But would that be this simple, flexible, transparent and compact as this approach?
Just as note, the standard edition of Symfony is shipped with SensioFrameworkExtraBundle, that allows to use annotations instead of file-based declaration:
/**
* #Route("/")
*/
public function indexAction()
{
// ...
}
In the same manner, you can set the prefix for the whole controller file:
/**
* #Route("/blog")
*/
class PostController extends Controller
{
/**
* #Route("/{id}")
*/
public function showAction($id)
{
}
}
Still, we have to declare it. I think the main reason is that routing requirements are heavily influenced by SEO optimizations. For anything that faces the public you want some keyword-rich URL. The "public" logic organization may also be different, you may have only one controller to deliver all your static pages, still you want those to be /contact, /about...
In some domains, routes can be inferred with conventions. If you create a REST API using FosRestBundle, it will auto-generate routes based on your controllers/actions names on the ressource approach. In general I think the FosRestBundle got a lot of things in their approach, you can easily parse and validate query parameters at the same time:
class FooController extends Controller
{
/**
* This action route will be /foo/articles, GET method only
*
* #QueryParam(name="val", default="75 %%")
*/
public function getArticlesAction(ParamFetcher $paramFetcher)
{
...
}
I always prefer having the routes in a config file rather than using annotations because, firstly, I feel it's more maintainable and easier to have an oversight. It's easier to ensure that you don't have any conflicting routes when you can see them all together.
Additionally, it's theoretically faster. Annotations require reflection, where the application needs to scan the file system and parse each controller to collect the set of routes.
The reason is probably maintainability for the long term. It doesn't matter how the routes are set up but generally, Laravel as a framework focuses on the simplicity and the small things that make the framework great. As long as it is easy to use for the user (web developer in this case), the goal is reached.
You can use a different name for the routes.php file and also use multiple route files, if you have a lot of routes in your application.
You can try and rethink the whole concept to improve it but I don't think that Laravel's routes need really a big change to make it even easier. It's already simple. Maybe it will be changed for the better in the future but for now, I think it's fine.

Flat PHP Legacy App - How to wrap in silex routes

I have been tasked with finding a solution to wrapping a custom made application in the silex framework as they are going to continue forward using silex. The dilemma is the legacy application is a flat php style with no controllers or models, and php with mysql queries embedded within the via files.
I have been struggling to find any clean solution to wrap the legacy app in the routing of silex to allow for new portions to be done in a controller based setyp instead of flat php. I have been checking for some time between stack overflow and other Google results, but they an del seem to end up specifying ways of doing default routes with a legacy app that has a controller based setup.
For good measure, the legacy app does use session variables so the solution must allow for those to be used.
Any and all help is appreciated.
Before people ask, I have looked at Routing in Silex/Symfony - Providing a default route and it is similar to how I would like to do it, but I need to make it work with the flat php app, not legacy controllers.
The solution ended up being a 2 part process.
Place the legacy code within the web root of the silex application.
Get the silex application to store sessions that are accessible by both Silex, and the legacy application.
Code Placement
By placing the legacy code into the web folder, anything in the URL that matches a file will go to that file instead of looking for a route. This allows for not needing to create routes for all of the old code, as it is not controller based in our situation and needs to be handled differently than most of the other restructuring that has been referred to on this site.
Placing the code into the web directory also means that we can continue to make updates and changes to the old code, while writing new Silex based code to replace it in our available time.
Sessions
When it came to using the same sessions, the option we went with was....less than desirable, but it allows for us to continue with our plans without hindering the use of either application. The current plan is to implement database stored sessions once we have completed migrating the application's code to Silex.
We went with an option first identified in this post Symfony session avoid _sf2_attributes. This is quite an ugly solution, but allows for the flexibility we need in attempting to migrate the application over in time with minimal effort up front. The goal is to migrate it over completely to the new Silex application, but the timeframe is over a year or more to do so.
Here is how the session is configured in our Silex application. It is using file based storage.
$app->register(new Silex\Provider\SessionServiceProvider(), array(
'cookie_lifetime' => 86400,
));
$app['session.storage'] = $app->share(function () use ($app) {
return new \Symfony\Component\HttpFoundation\Session\Storage\LegacySessionStorage;
});
Here is a copy of the controller code located originally here, in case it is removed at some point.
<?php
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
/**
* Session sotrage that avoids using _sf2_attributes subkey
* in the $_SESSION superglobal but instead it uses
* the root variable.
*/
class LegacySessionStorage extends NativeSessionStorage
{
const SYMFONY_SESSION_SUBKEY = '_sf2_attributes';
/**
* #inheritdoc
*/
protected function loadSession(array &$session = null)
{
if (null === $session) {
$session = &$_SESSION;
}
parent::loadSession($session);
foreach ($this->bags as $bag) {
$key = $bag->getStorageKey();
if (self::SYMFONY_SESSION_SUBKEY === $key)
{
$bag->initialize($session);
}
}
}
}
I hope this helps some others in allowing them to migrate to a new coding style from an old application that is a thorn in their side. Wanted to make sure to sum up our findings over time in order to ensure others don't have to look as much in the future hopefully.
there is a really good article written by Matthias Noback about this. Basically the trick would be to match the legacy urls and return the legacy output inside a Silex Response object. Beware of memory use with ob_* methods.
An alternative is to modernize the flat PHP application in place (leaving you with one unified codebase) instead of wrapping it (which leaves you with 2 codebases). The step-by-step details are in Modernizing Legacy Applications in PHP but the overview is this:
Implement an autoloader
Consolidate classes and functions to a central location
Remove globals in favor of dependency injection
Remove the new keyword in favor of dependency injection
Write unit tests
Extract SQL code to Gateway classes ("Model, Part 1")
Extract domain logic to Transaction classes ("Model, Part 2")
Extract presentation logic to Response classes ("View")
Extract action logic to Controller classes ("Controller")
Extract remaining includes
Extract application code from the document root
Implement a front controller
Prepare the application for a dependency injection container
Add a dependency injection container
Hope that helps.

Developing web pages in a multi site application

I'm developing several web sites in Kohana using its template system so that one code base is running several web sites using the same back end DB. I'm starting to see a lot of if statements in the views to say if this site do this, if that site do that. It starting to look very non-MVC or Object Oriented. Do other developers have any rules they follow when deciding to breakout view into separate partial views? I want to reuse as much of the code as possible but not swim in if statement in every view. Any reference would be great also.
If you are using Kohana, you should use modules for stuff you don't want to duplicate for every application. Then you can keep specifics in your application with extended classes or specific settings in config files.
http://kohanaframework.org/3.2/guide/kohana/modules
A lot of if statements are mostly an indication that you need to do refactoring. A large cascading if statement to allow for different sites to be loaded is bad practice in the sense that you make files tightly coupled causing to edit multiple files when you need to make a simple addition or change. Furthermore, it will eventually become ugly if every site needs to load different dependencies or settings or whatever in your if statement.
It's difficult to say what you need to change without seeing the code, but try looking at design patterns like the factory or abstract factory design patterns to create site objects.
A good book that deals with the subject of patterns and best practices with PHP is PHP 5: Objects, Patterns and Practice by Matt Zandstra: http://www.amazon.com/PHP-5-Objects-Patterns-Practice/dp/1590593804. A very good book.
I had a similar issue cropping up with this, to keep the views nice and neat I extended the view class into a theme class. I would give the factory method two (or more) views ie Theme::factory(array('site1/home','default/home'),$data)->bind(...); If a themed view existed it would use that, else just serve up the default. That way I, or someone else less competent could easily override to display structure and view behaviour.
The class looks like this
class Theme extends View {
public static function factory($pages = NULL, array $data = NULL){
if (is_string($pages)) {
$pages=array($pages);
}
if (!is_array($pages)) {
$pages=array(0=>null);
}
foreach ($pages as $page){
if ((Kohana::find_file('views', 'themes/'.$page)) !== FALSE){
return new View('themes/'.$page,$data);
}
}
throw new Kohana_View_Exception("None of the requested views ':file' could not be found.", array(
':file' => join($pages,"' or '"),
));
}
}
You really want ViewModels, only you don't know how to name them yet. Little birds have been tweeting that it'll be in Kohana 3.3 but unless you have a year or so to wait, I recommend trying either View-Model module by Zombor or moving away from Kohana's templating system whatsoever in favour of KOstache (it's Mustache for Kohana)
If for any reason you want to stick with your current codebase, I'd go with splitting the view into several smaller interchangable parts and loading them when necessary (echo View::Factory(($something == 'one' ? 'view_one' : 'view_two')) or a custom written helper would be a nice toy here)

PHP application structure

I started making a website, and quickly i found out that my code is a mess. It's been a while since I've been programming in PHP, and since then I learned OOP. Now while making an application in C# or java is pretty easy from this point of view, PHP is giving me trouble.
I used to program everything (in php) just from one line to another, with minimum amount of methods and no classes at all. So how much should be in methods, and where should this classes be?
Example:
I have account.php, and i want to update user information. So after checking that someone has sent some data if(isset($_POST[.. what next? I used to just make
all the checks like $email=CheckForRisksOrSomething($_POST["email]); and then just update mysql.
This brings me to the question, should I create a class User and what methods should it contain? Also WHERE should this class be saved, assuming that user.php would show you user's profile.
Back to how much should be in classes, should i just use in a file like:
$smth = new Someclass();
if($smth->checkIfSaved()){
$user = new User();
$user->updateUser(/* all the $_POST stuff here? */);
} else {
$smth->showUserDetailsForm();
}
Also where should Someclass be saved?
So if ayone would give me an example of how to structure the following functionalities (in files, classes and possibly methods).
users (registration, login, editing account..)
picture with comments of it
news (also with comments)
administration
This is just an example of course, but i don't want to keep on with my mess and then look at it three days later and just facepalm and wonder what did i write there. Well, i already did that today, that's why I'm asking.
EDIT 24.2.2016
While this is an old question, as suggested look into a framework. While it might take a bit to set it up it increases development speed, code is nice and clean and a lot safer. I personally use Laravel.
There's more than one way to skin this cat, but I'll recommend some helpful links and books for you.
Zend's Coding Standards: If you're looking at how to structure, name, etc. your files, then I would look at how Zend suggests to do these things. By following their guidelines, you can create a package that is compatible with somebody else's code using these same methods, as well.
What you will want to do is create a folder specifically for your classes. How do you know when you'll need to make a new class, and what to include? Good question!
If you find yourself running into groups of information that is related, needs to be handled together a lot, or solves a particular problem, chances are you should create a new class that can handle it.
For example, a User class to handle any sort of changes you want to make to a user of your site. Another example is a Role class that can perform tasks (or not) depending on if they're an admin or not. The wonderful thing about Objects and Classes is you can create a User::$role (variable named $role in the User class) that is a Role class. So for instance, you will have a Role object in your User object. From here, your user object can now call to the role object by doing something like:
class User {
private $username;
private $role;
function __construct($username){
$this->username = $username;
}
public function setRole($roleType){
switch($roleType){
case "admin":
$this->role = new Admin(); // contained in another class file
break;
case "staff":
$this->role = new Staff(); // contained in another class file
break;
default:
$this->role = new Visitor(); // contained in another class file
} // end case
} // end setRole
} // end Class User
$loggedInUser = new User("Bubba");
$loggedInUser->setRole("admin");
$loggedInUser->role->deleteMessage();
In general, you will want to keep your code structured and separate, so that each class only handles information that it should have, and not do anything more than it should. If you find a class doing too many things, this means you found a good time to create another class to handle this new responsibility. How you tie it all together is generally a problem answered with "design patterns". There is a very good book that covers both programming using objects and classes, as well as using design patterns.
Check out the book "PHP 5 Objects, Patterns, and Practice" by Matt Zandstra, and published by Apress. It's a wonderful book that dips your toes into OOP with PHP!
It is very hard to tell you how you should do that. There are many different preferences out there. Look at frameworks like Zend, Kohana, CodeIgniter, and so forth.
When I create smaller applications with OOP design, I usually try to follow the following hierarchy:
In the index.php include a bootstrap.php.
In the bootstrap.php include all classes and the config.
Make a classes directory where you can save core functionallity in a core folder.
Furthermore, in your classes directory create the two folders controllers and models.
In my projects I usually have another folder templates, where all my html files go in (and afterwards get rendered with the Smarty Template Engine).
This is a very simplified approach, but can lead you in the right direction. For your requirements like users, pictures, etc. create a model that contains all the data of one single user.
class UserModel() {
public $name;
public $email;
}
And then a controller that can modify this model:
class UserController() {
public function update($user) {
...
}
}
My answer might not be directly answering your questions but might do you lot of good.
Go with a real framework. Don't build websites with code from scratch. It will save you huge amount of time and will force you to use good practices of code separation, really good and clean project structure but again, it will save you time! For many things you decide to implement there there will be a ready solution and the common thing you do (as validate email address) would be done the right way.
I would go with a MVC PHP framework and after having used a lot CakePHP, Zend, Kohana and few others in the past, I would recommend you to go with Yii. Very small learning curve, nice docs, nice big active community and you will be able to port whatever you already have, to it in very small time.
I'm pretty sure for the project you've described that framework will cut your time at least 2 times and in the same time you will have all the things you ask above already solved. I know this from experience, having developed projects from scratch quite some time ago.
if you are developing for web, there are high chances that you will be developing a MVC application, simplest MVC framework known to me is CodeIgniter. And I will advice you to use it.

Writing my own PHP framework, need some opinions/suggestions on an approach

Before I begin, this framework is not meant to compete with Zend, Symfony, Cake or any other framework. It is primarily a personal project so that I may test out some PHP 5.3 goodies, experience new techniques and gives me the chance to try things under my idea. I am also trying to make this framework as lightweight as possible, and reduce the amount of unncessary getters and setters. Now for the problem at hand.
A bulk of the framework is done, primarily all the core classes required for it to run. The problem arises on the entry point of the application. I want the whole application to be run through a single core object which branches out. The core object will be extended with classes to manage environments, configuration, registry, autoloading, routing, etc, etc. You can see this "core" object below, it is aptly called Application.
https://github.com/titon/titon/blob/42c88e36c29e3d8c697306fe68be18b3a8fd2e70/titon/source/Infrastructure.php
$app = new \titon\source\core\Application();
The idea was that from anywhere in the application, you can access the core objects through this $app variable. Example:
(I cant post more than 1 link, so please go to the following directories on Github. /app/config/Setup.php and /app/modules/core/Bootstrap.php)
$app->environment->current();
$app->loader->includePath(array(__DIR__));
$app->registry->factory('titon\source\system\Controller');
But now we get into the problem of global variables, which I do not want to use. I also like to try and avoid Singletons.
public function foobar() {
global $app; // Eww
}
But I also do not want to use static classes, as I was trying to go for a more OOP approach. The only solutions I can think of is using a static class property to hold the Application instance and access that everywhere, but I do not like that. Or I can pass the object down to its children over and over again, but again, not a fan.
Core::$app->router->detect(); // Meh
$this->setApplication($this); // Mehher
I was curious how Zend and Symfony approached this problem. But after looking through their source code, I could not backwards engineer and determine the correct entry point. Furthermore, it seemed Zend would created global variables all over (Zend_Config, etc), but I would prefer to have a managing object. Symfony 2.0, I just got lost. As for Cake, Solar, Fuel, it seems they are using static classes for these kind of objects.
Now my primary question is, how would you solve this? I would like to keep a single object to instantiate and be accessible everywhere, but it doesn't seem like an easy thing to handle. I am willing to rewrite a lot of the framework if need be.
The idea was that from anywhere in the application, you can access the core objects through this $app variable. Example:
...
But now we get into the problem of global variables, which I do not want to use. I also like to try and avoid Singletons.
That seems like a contradiction to me.
Do you know why you don't want any global variables? Is it because you read somewhere that global variables are a bad thing?
Conversely, do you know why you want a central object that is available from anywhere in your application?
Follow Up:
In case it wasn't clear, those were meant as rhetorical questions. From an architectural viewpoint, global variables (in any shape) are expensive. Some say evil. I think that's missing the point slightly - You need some amount of global variables in any application (At least one). To further muddy the waters, "global" is really a relative thing; It is much more meaningful to consider variables as having varying scopes, where global is on one extreme of the continuum and local, temporary variable at the other. If you have a single object containing all your other objects, then I would consider each of these variables as being effectively global variables, even though they may not be so in a technical sense. Think a bit about that.
As for a silver bullet, you could take a look at dependency injection. This is an approach to avoiding global variables that works, but has some cost in the form of complexity.
One of PHP's old unresolved issues: One can't define superglobals, without using a extension like runkit.
I usually solve this with a pseudo-Registry, i.e. I define a class R with all variables I want to make global defined as public static $var. I know, this is probably not the vanilla-OOP approach, but it serves well. R::$var is as short as it get, I think. Everything else, like dependency injection ($this->var) or singleton (R::getVar()), is longer.
The best solution to avoid global variables is dependency injection. You'll probably need to create some container. Look at the Symfony components library.
You may also try registry pattern.

Categories