Integrating Mobile Money to Symfony - php

I have a Symfony application which I will like to integrate mobile money into. The problem is I cannot add PHP code to twig files and I am a complete newbie to this kind of challenge. The code reads:
<?php
require_once '/path/to/monetbil-php/monetbil.php';
// Setup Monetbil arguments
Monetbil::setAmount(500);
Monetbil::setCurrency('XAF');
Monetbil::setLocale('en'); // Display language fr or en
Monetbil::setPhone('');
Monetbil::setCountry('');
Monetbil::setItem_ref('2536');
Monetbil::setPayment_ref('d4be3535f9cb5a7aff1f84fa94e6f040');
Monetbil::setUser(12);
Monetbil::setFirst_name('KAMDEM');
Monetbil::setLast_name('Jean');
Monetbil::setEmail('jean.kamdem#email.com');
// Start a payment
// You will be redirected to the payment page
Monetbil::startPayment();
I am looking at adding this to App/Resources/Views/members/dashboard.html.twig

Twig is only ment to render your output. Put your (php) logic in your controller and/or create your own service. From your controller you will also render your Twig template with the variables you need but only to render the output that you want to show to the users.

If you're using a framework like Symfony, you shouldn't use require_once (except some exceptions). Read about autoloading and dependency injections (Symfony.com has excellent articles).
For some reason, the monetbil-php library doesn't use composer. I don't know why, but I can imagine three reasons: they don't know what it is (hello developers, it's 2017!), they hate other developers or the library hasn't been updated for years. Despite the recent commits, it looks like a very outdated library (why still supporting PHP 5.2? That's from the dark ages!). Sorry for this slightly offtopic rant, back to the question.
For now, copy the files to your project, give the file a namespace and use it in your project. I've opened an issue here because I think the developers should add a composer file if they want their users to use their library in a framework like Symfony.
The PHP code should be in your controller* since you can't use PHP in Twig and even if you could, you shouldn't. Monetbil defines business logic, so it shouldn't be in a template.
To use it in your controller:
/**
* Pay the bill
*
* #Route("/pay/{id}", name="payment")
* #Method("POST")
* #param Request $request
* #param Order $product
*
* #return JsonResponse
* #throws \Exception
*/
public function payAction(Request $request, Order $product)
{
Monetbil::setAmount(500);
//..
Monetbil::startPayment();
}
According to the comment, startPayment() will redirect, so there's nothing to return to the Twig template.
(*) Business logic in your template is considered as a bad practice, but you should prevent putting too many business logic in a controller too. If you have this example working, try to read about services so you can define the business logic in a framework-agnostic way. It makes maintaining your application (unit tests, Symfony updates, maybe switch to another framework?) easier.

Related

Optimization - Two similar method

I'm new in Symfony and i have a little problem.
I been searching online, couldn't find the answer to my problem.
I create API and I have two controllers(UserController, InstructorController) with similar method (addUserImage, addInstructorImage). I created abstract BaseImage(Here is saving files), InstructorImage and UserImage(here are set path). This is my controller:
/**
* #ApiDoc(
* name="addInstructorImage", section="Instructors",
* description="Add Instructor Image",
* )
*
* #Route("/instructor/{instructor}/image", name="instructors.image.add")
* #Method("POST")
*
* #param Request $request
* #param Instructor $instructor
* #View
*
* #return \FOS\RestBundle\View\View
*/
public function addInstructorImage(Request $request, Instructor $instructor)
{
$this->denyAccessUnlessGranted('edit', $instructor->getUser());
$image = new InstructorImage();
$form = $this->get('form.factory')
->createNamed('', InstructorImageType::class, $image, ['csrf_protection' => false, 'method' => 'POST']);
$form->handleRequest($request);
if ($form->isValid()) {
$image->setInstructor($instructor);
$em = $this->getDoctrine()->getManager();
$em->persist($image);
$em->flush();
return $this->view(null, Response::HTTP_NO_CONTENT);
}
return $this->view($form, Response::HTTP_BAD_REQUEST);
}
My second controller is identical.
The only difference is another object , and another form. What is the best way to optimize this code. Should I create services that adds photos or use chain handler? Maybe You have better ideas?
Thank you for your help
Short answer: Don't waste time on trying to optimize this sort of stuff.
Your method consist of 19 lines of code. It's all basic boiler plate easy to read code. I know whenever I see duplicate code I'm tempted to try and combine it somehow but what exactly would be gaining? Reducing 19 lines to maybe 15?
If I was going to change your code then I'd be tempted to move some of the business logic into it's own service. Something like:
InstructorManager::addImage($instructor,$image);
That would get rid of the entity manager boiler plate and provide a bit of abstraction. Might make it a bit easier to test though all the method is doing is setting the image and calling flush. Hardly worth the effort. Might be worth it if you have other manager type functionality to add as well. Or maybe you want to be able to add images from a console app.
Of course you may end needing to add functionality in the future. Maybe you want to notify someone when the image is changed. If you find yourself needing to modify duplicated code then you can probably justify the effort of moving common code into it's own service.
And I suppose you could create a service for your form using the container's factory capability. Especially if you had a bunch of these form to make. But again, hardly worth the effort and might even make things more difficult to maintain.

How to solve some problems in symfony 2?

I started to explore the world of Symfony 2 now and face with some realy strange problems i would not think they can occure in such a professional framework. I will show you the problems i face one by one:
1) How to get the recent actionName?
I found only this solution which is imho semiprofessional:
$request->attributes->get('_controller');
// will get yourBundle\Controller\yourController::CreateAction
$params = explode('::',$request->attributes->get('_controller'));
// $params[1] = 'createAction';
$actionName = substr($params[1],0,-6);
Is this serious, i have to do some extra-work to get it, why.. Is there a better solution? Creating a base controller class with a method e.g. getActionName(), but why do i have to implement such basic functionality in a framework. Is there a other way?
2) When i forward a request the code in 1) will not work.
$request = $this->container->get('request');
$getParameterList = $request->query->all();
if (!empty($getParameterList['mode'])
&& $getParameterList['mode'] == 1) {
return $this->forward('AcmeDemoBundle:Routing:lawyersearch', array(), $getParameterList);
}
The reason why it will not work is that "AcmeDemoBundle:Routing:lawyersearch" is a other format than when i came directly from a route. Second problem here is that i have to forward the GET-paramters as well(i think POST too). Is there a way that i do not have to care about it?
3) How to use a default template without using this annotation:
/**
* #Template()
*/
public function indexAction()
{
return array();
}
I do not want to have above all my methods this annotation; i know i can put it on the top of the class definition. Is there a way to achieve this? The only solution i see, is to write a BaseController that determines by a method out of the module/controller/action the default template.
4) I found classes that use public attributes e.g. Symfony\Component\Validator\Constraints\Length with e.g. public $max;
How to solve this? Very strange because this is not professional to use public attributes.
I hope someone has easy solutions for this. It would be realy dissapointing if Symfony 2 has so much strange behaviour in so much cases. 4 strange things i 2 days since i began to explore it. It gives me the feeling that there is much more when i continue.
Please confirm that there are no other solution by the framework or which is the solution. Thank you
1) By accessing the '_controller' parameter of the request, you are delving into the internals of Symfony2. They rarely document anything related to this outside of routing. You should use controller actions more definitively, don't try to automate too much on this level.
2) Symfony2 can't account for highly dynamic controllers. You know it is possible to call ->forward more than once, and within the same controller action. This creates a nesting nightmare that the Symfony developers weren't prepared to deal with.
This is one of the reasons $request = $this->container->get('request'); is now deprecated in favour of $stack = $this->container->get('request_stack');. Because forwarding needs to create new internal requests.
3) Also deprecated. Symfony2 best practices now discourages the use of #Template() with empty parameters because of the potentially volatile development of actions/templates. You are supposed to explicitly define which template to use, if you use one at all. This comes in handy when dealing with data-only responses. You wouldn't want your responses to use a template automatically as this would result in unexpected behaviour in your design.
1) Use Constant: __FUNCTION__
http://php.net/manual/en/language.constants.predefined.php
2) Try setMethod on $request:
$this->get('request')->setMethod('POST');
3) I do not know, probably not possible.
4) Symfony\Component\Validator\Constraints\Length is one of constraints:
http://symfony.com/doc/current/book/validation.html#constraints

PHP folder structure for AJAX calls and form actions

I am trying to develope good code organization habits and work exclusively with OOP in php but I can't seem to wrap my head around something.
Here is a simplified description of what I am working with:
I have all my class files in a folder '/resources/Classes'
I have all my html and javascript in '/public_html' & '/public_html/script respectively'
My question is concerning files that are the actions of forms or AJAX requests. For example 'formAction.php' and 'ajaxURL.php'. These files are not Classes and also do not contain any html or other such GUI.
I have been putting them in a folder 'resources/actions' but my gut tells me something about this is not fully OOP.
Is my usage of these files incorrect if I am trying for complete OOP? if so how can I approach this differently.
Here is an actual file from my project as a concrete example:
//file: getBalance.php
<?php
/**
* This script gets the balance of an account from the server
*/
if (!isset($Database)) {
$Database = require_once "../clear_finance_pkg.php";
}
/** #var User $User */
$User = $Database->getUserByID("1");//TODO: user should be set dynamically
$User->setAccounts($Database->getAccountsByUser($User));
if (isset($arg1)) {
$accountID = $arg1;
foreach ($User->getAccounts() as $Account) {
if ($Account->getId() == $accountID) {
$RbcChequing = RbcAccount::accountToRbcAccount($Account, "Chequing");
echo '$' . Money::toDollars($RbcChequing->getBalance());
break;
}
}
} else throw new Exception('Account ID is not set. Could not get balance');
It's difficult to say if your code is complete OOP, but i think it isn't. It looks like you are on the right track, because you are using classes, objects and methods. That's the basic of OOP. No longer large if/else statements and a lot of variables that doesn't make sense, but objects and methods without code-duplication.
I think your question in more related to the seperation of logic and view. First of all. In general it's ok to make a file for a function, but in a large application you will loose the overview. What you are doing know is combine view-related and logic-related things in one file, but actually that's not what you want. The ideal situation is full seperation of logic and view so you can create multiple seperate views based on the same logic.
My advice is to take a look at the MVC-pattern. Take a look at this link. It will help you to get a basic understanding of the MVC-pattern. Notice that you won't longer need to have a file for each function. And you have a seperation of your logic and view elements because you can use the same model in multiple views (although this is maybe not the best example).

Can you automatically put a method's code into its DockBlock in phpDocumentor 2?

I've installed phpDocumentor 2 and want to include the source for each method in the generated documentation. However, I notice that the inline #source tag does not appear to be picked up, and there only seems to be reference to it in phpDocumentor 1's documentation.
Here's what I've been trying:
/**
* Test Comment
*
* {#source}
*/
public function test_method() {
echo('Hi!');
}
I was hoping {#source} would be replaced with the following HTML:
<code>
echo('Hi!');
</code>
Is this now deprecated? And if so, is there any way to achieve this using phpDocumentor 2?
I've had a proper look into this today and spoken with Mike van Riel on the phpDocumentor mailing list.
Simply put - you can't do exactly what I'm after.
PHPDocumentor 2's default template, 'responsive', has no support for dynamically showing code. What you can do is switch to an alternate template, 'new-black', and that will show you the source code for the corresponding file. This works with the #filesource tag and there's a --sourcecode switch when building the documentation which will automatically enable this for all files.
However, what you can't do is include code at method level, which is what the #source tag is for. That simply isn't supported, and the raw structure.xml file doesn't even store this information.
Having said that, Mike has said "I definitely want the functionality" - so here's to hoping it gets included in the future! I haven't got time this second, but I'll submit it as an issue on GitHub. If you're keen on having this functionality too, please make it known.

Dynamic form building / metaprogramming / PHP

I'm looking for design ideas about creating dynamic forms.
What I currently have is a bunch of models with a few properties / variables for example:
class Group extends IDKModel {
/**
* #Form
*/
public $title;
/**
* #Form(validation="{my validation rules here}")
*/
public $permissions;
}
In that example the Form PHPAnnotation defines it as a form element and the validation array will have built in validation rules in it. Now the problem I'm having is I have no idea how to implement conditionals.
For example, how to show $permissions only if a user is an admin. How to show $title if time of day is past 12:00 GMT. Basically any kind of conditional.
Taken from #php at irc.quakenet.org:
[10:50] <ramirez> i would not try to stick all of the meta-info under one attribute
[10:50] <ramirez> it'd be much cleaner to do something like
[10:50] <ramirez> #FormElement
[10:51] <ramirez> #Validator(params)
[10:51] <ramirez> etc
[10:52] <ramirez> anyways, I would probably do something like.. #Filter(name="Group",value="admin,editor")
[10:53] <ramirez> then for each filter you want to implement, you'll create a class like "Model_Filter_Group", which would be used for eg. the above filter
[10:53] <ramirez> that class in this case would simply explode the groups by comma and see if user is in any of those groups
[10:54] <ramirez> you can use that for any kind of filtering, eg: #Filter(name="PastTime", value="12:00")
Anyone have a simpler idea?
I suggest you take a look to Zend_Form component in Zend Framework:
Zend Framework Reference:Zend_Form
Zend_Form is very powerful and highly customizable but can be a bit too complex to see all of its capabilities provided by good OOP design.
Even if ZF of no use for you, you can find good ideas there.
btw: manual covers only basics as well as tutorials found on the web

Categories